001 /****************************************************************
002 * Licensed to the Apache Software Foundation (ASF) under one *
003 * or more contributor license agreements. See the NOTICE file *
004 * distributed with this work for additional information *
005 * regarding copyright ownership. The ASF licenses this file *
006 * to you under the Apache License, Version 2.0 (the *
007 * "License"); you may not use this file except in compliance *
008 * with the License. You may obtain a copy of the License at *
009 * *
010 * http://www.apache.org/licenses/LICENSE-2.0 *
011 * *
012 * Unless required by applicable law or agreed to in writing, *
013 * software distributed under the License is distributed on an *
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
015 * KIND, either express or implied. See the License for the *
016 * specific language governing permissions and limitations *
017 * under the License. *
018 ****************************************************************/
019
020 package org.apache.james.jspf.impl;
021
022 import org.apache.james.jspf.core.LogEnabled;
023 import org.apache.james.jspf.core.Logger;
024 import org.apache.james.jspf.core.exceptions.PermErrorException;
025 import org.apache.james.jspf.parser.TermDefinition;
026 import org.apache.james.jspf.parser.TermsFactory;
027 import org.apache.james.jspf.terms.Configuration;
028 import org.apache.james.jspf.terms.ConfigurationEnabled;
029 import org.apache.james.jspf.wiring.WiringService;
030 import org.apache.james.jspf.wiring.WiringServiceException;
031 import org.apache.james.jspf.wiring.WiringServiceTable;
032
033 import java.io.IOException;
034 import java.io.InputStream;
035 import java.util.ArrayList;
036 import java.util.Collection;
037 import java.util.Collections;
038 import java.util.Properties;
039
040 /**
041 * The default implementation of the TermsFactory
042 */
043 public class DefaultTermsFactory implements TermsFactory {
044
045 private String termFile = "org/apache/james/jspf/parser/jspf.default.terms";
046
047 private Collection<TermDefinition> mechanismsCollection;
048
049 private Collection<TermDefinition> modifiersCollection;
050
051 private Logger log;
052
053 private WiringService wiringService;
054
055 public DefaultTermsFactory(Logger log) {
056 this.log = log;
057 this.wiringService = new WiringServiceTable();
058 ((WiringServiceTable) this.wiringService).put(LogEnabled.class, log);
059 init();
060 }
061
062 public DefaultTermsFactory(Logger log, WiringService wiringService) {
063 this.log = log;
064 this.wiringService = wiringService;
065 init();
066 }
067
068 /**
069 * Initialize the factory and the services
070 */
071 private void init() {
072 try {
073 InputStream is = Thread.currentThread().getContextClassLoader()
074 .getResourceAsStream(termFile);
075 if (is == null) {
076 throw new NullPointerException("Unable to find the "+termFile+" resource in the classpath");
077 }
078 Properties p = new Properties();
079 p.load(is);
080 String mechs = p.getProperty("mechanisms");
081 String mods = p.getProperty("modifiers");
082 String[] classes;
083 classes = mechs.split(",");
084 Class<?>[] knownMechanisms = new Class[classes.length];
085 for (int i = 0; i < classes.length; i++) {
086 log.debug("Add following class as known mechanismn: "
087 + classes[i]);
088 knownMechanisms[i] = Thread.currentThread()
089 .getContextClassLoader().loadClass(classes[i]);
090 }
091 mechanismsCollection = createTermDefinitionCollection(knownMechanisms);
092 classes = mods.split(",");
093 Class<?>[] knownModifiers = new Class[classes.length];
094 for (int i = 0; i < classes.length; i++) {
095 log.debug("Add following class as known modifier: "
096 + classes[i]);
097 knownModifiers[i] = Thread.currentThread()
098 .getContextClassLoader().loadClass(classes[i]);
099 }
100 modifiersCollection = createTermDefinitionCollection(knownModifiers);
101
102 } catch (IOException e) {
103 throw new IllegalStateException(
104 "Term configuration cannot be found");
105 } catch (ClassNotFoundException e) {
106 throw new IllegalStateException(
107 "One configured class cannot be found");
108 }
109 }
110
111
112 /**
113 * Create a collection of term definitions supported by this factory.
114 *
115 * @param classes
116 * classes to analyze
117 * @param staticFieldName
118 * static field to concatenate
119 * @return map <Class,Pattern>
120 */
121 private Collection<TermDefinition> createTermDefinitionCollection(Class<?>[] classes) {
122 Collection<TermDefinition> l = new ArrayList<TermDefinition>();
123 for (int j = 0; j < classes.length; j++) {
124 try {
125 l.add(new DefaultTermDefinition(classes[j]));
126 } catch (Exception e) {
127 log.debug("Unable to create the term collection", e);
128 throw new IllegalStateException(
129 "Unable to create the term collection");
130 }
131 }
132 return Collections.synchronizedCollection(l);
133 }
134
135
136 /**
137 * @see org.apache.james.jspf.parser.TermsFactory#createTerm(java.lang.Class, org.apache.james.jspf.terms.Configuration)
138 */
139 public Object createTerm(Class<?> termDef, Configuration subres) throws PermErrorException, InstantiationException {
140 try {
141 Object term = termDef.newInstance();
142
143 try {
144 wiringService.wire(term);
145 } catch (WiringServiceException e) {
146 throw new InstantiationException(
147 "Unexpected error adding dependencies to term: " + e.getMessage());
148 }
149
150 if (term instanceof ConfigurationEnabled) {
151 if (subres == null || subres.groupCount() == 0) {
152 ((ConfigurationEnabled) term).config(null);
153 } else {
154 ((ConfigurationEnabled) term).config(subres);
155 }
156 }
157 return term;
158 } catch (IllegalAccessException e) {
159 throw new InstantiationException(
160 "Unexpected error creating term: " + e.getMessage());
161 }
162 }
163
164
165 /**
166 * @see org.apache.james.jspf.parser.TermsFactory#getMechanismsCollection()
167 */
168 public Collection<TermDefinition> getMechanismsCollection() {
169 return mechanismsCollection;
170 }
171
172
173 /**
174 * @see org.apache.james.jspf.parser.TermsFactory#getModifiersCollection()
175 */
176 public Collection<TermDefinition> getModifiersCollection() {
177 return modifiersCollection;
178 }
179
180 }