001: /*
002: * Copyright 2005 Joe Walker
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.directwebremoting.impl;
017:
018: import java.util.Arrays;
019: import java.util.Collection;
020: import java.util.Collections;
021: import java.util.HashMap;
022: import java.util.List;
023: import java.util.Map;
024:
025: import org.apache.commons.logging.LogFactory;
026: import org.apache.commons.logging.Log;
027: import org.directwebremoting.WebContext;
028: import org.directwebremoting.WebContextFactory;
029: import org.directwebremoting.extend.Creator;
030: import org.directwebremoting.extend.CreatorManager;
031: import org.directwebremoting.util.LocalUtil;
032: import org.directwebremoting.util.Messages;
033:
034: /**
035: * A class to manage the types of creators and the instantiated creators.
036: * @author Joe Walker [joe at getahead dot ltd dot uk]
037: */
038: public class DefaultCreatorManager implements CreatorManager {
039: /**
040: * Set the debug status
041: * @param debug The new debug setting
042: */
043: public void setDebug(boolean debug) {
044: this .debug = debug;
045: }
046:
047: /* (non-Javadoc)
048: * @see org.directwebremoting.CreatorManager#isDebug()
049: */
050: public boolean isDebug() {
051: return debug;
052: }
053:
054: /* (non-Javadoc)
055: * @see org.directwebremoting.CreatorManager#addCreatorType(java.lang.String, java.lang.String)
056: */
057: public void addCreatorType(String typeName, String className) {
058: if (!LocalUtil.isJavaIdentifier(typeName)) {
059: log.error("Illegal identifier: '" + typeName + "'");
060: return;
061: }
062:
063: Class<? extends Creator> clazz = LocalUtil.classForName(
064: typeName, className, Creator.class);
065: if (clazz != null) {
066: log.debug("- adding creator type: " + typeName + " = "
067: + clazz);
068: creatorTypes.put(typeName, clazz);
069: }
070: }
071:
072: /* (non-Javadoc)
073: * @see org.directwebremoting.CreatorManager#addCreator(java.lang.String, java.lang.String, java.util.Map)
074: */
075: public void addCreator(String scriptName, String creatorName,
076: Map<String, String> params) throws InstantiationException,
077: IllegalAccessException, IllegalArgumentException {
078: Class<? extends Creator> clazz = creatorTypes.get(creatorName);
079: if (clazz == null) {
080: log.error("Missing creator: " + creatorName
081: + " (while initializing creator for: " + scriptName
082: + ".js)");
083: return;
084: }
085:
086: Creator creator = clazz.newInstance();
087:
088: LocalUtil.setParams(creator, params, ignore);
089: creator.setProperties(params);
090:
091: // add the creator for the script name
092: addCreator(creator.getJavascript(), creator);
093: }
094:
095: /* (non-Javadoc)
096: * @see org.directwebremoting.CreatorManager#addCreator(java.lang.String, org.directwebremoting.Creator)
097: */
098: public void addCreator(String scriptName, Creator creator)
099: throws IllegalArgumentException {
100: // Check that we don't have this one already
101: Creator other = creators.get(scriptName);
102: if (other != null) {
103: throw new IllegalArgumentException(Messages.getString(
104: "DefaultCreatorManager.DuplicateName", scriptName,
105: other.getType().getName(), creator));
106: }
107:
108: // Check that it can at least tell us what type of thing we will be getting
109: try {
110: Class<?> test = creator.getType();
111: if (test == null) {
112: log.error("Creator: '" + creator + "' for "
113: + scriptName
114: + ".js is returning null for type queries.");
115: } else {
116: log.debug("- adding creator: "
117: + creator.getClass().getSimpleName() + " for "
118: + scriptName);
119: creators.put(scriptName, creator);
120: }
121: } catch (NoClassDefFoundError ex) {
122: log.error("Missing class for creator '" + creator
123: + "'. Cause: " + ex.getMessage());
124: } catch (Exception ex) {
125: log.error("Error loading class for creator '" + creator
126: + "'.", ex);
127: }
128:
129: // If this is application scope then it might make sense to create one
130: // now rather than wait for first use. Otherwise this job is done by
131: // DefaultRemoter.execute(Call call)
132: if (initApplicationScopeCreatorsAtStartup
133: && creator.getScope().equals(Creator.APPLICATION)) {
134: try {
135: WebContext webcx = WebContextFactory.get();
136: Object object = creator.getInstance();
137: webcx.getServletContext().setAttribute(
138: creator.getJavascript(), object);
139:
140: log.debug("Created new " + creator.getJavascript()
141: + ", stored in application.");
142: } catch (InstantiationException ex) {
143: log.warn("Failed to create " + creator.getJavascript(),
144: ex);
145: log
146: .debug("Maybe it will succeed when the application is in flight. If so you should probably set initApplicationScopeCreatorsAtStartup=false in web.xml");
147: }
148: }
149: }
150:
151: /* (non-Javadoc)
152: * @see org.directwebremoting.CreatorManager#getCreatorNames()
153: */
154: public Collection<String> getCreatorNames()
155: throws SecurityException {
156: if (!debug) {
157: throw new SecurityException();
158: }
159:
160: return Collections.unmodifiableSet(creators.keySet());
161: }
162:
163: /* (non-Javadoc)
164: * @see org.directwebremoting.CreatorManager#getCreator(java.lang.String)
165: */
166: public Creator getCreator(String scriptName)
167: throws SecurityException {
168: Creator creator = creators.get(scriptName);
169: if (creator == null) {
170: StringBuffer buffer = new StringBuffer(
171: "Names of known classes are: ");
172: for (String key : creators.keySet()) {
173: buffer.append(key);
174: buffer.append(' ');
175: }
176:
177: log.warn(buffer.toString());
178: throw new SecurityException(Messages.getString(
179: "DefaultCreatorManager.MissingName", scriptName));
180: }
181:
182: return creator;
183: }
184:
185: /* (non-Javadoc)
186: * @see org.directwebremoting.CreatorManager#setCreators(java.util.Map)
187: */
188: public void setCreators(Map<String, Creator> creators) {
189: this .creators = creators;
190: }
191:
192: /**
193: * Do we do full-create on startup?
194: * @return true if we are doing full-create
195: */
196: public boolean isInitApplicationScopeCreatorsAtStartup() {
197: return initApplicationScopeCreatorsAtStartup;
198: }
199:
200: /**
201: * Do we do full-create on startup?
202: * @param initApplicationScopeCreatorsAtStartup true for full create
203: */
204: public void setInitApplicationScopeCreatorsAtStartup(
205: boolean initApplicationScopeCreatorsAtStartup) {
206: this .initApplicationScopeCreatorsAtStartup = initApplicationScopeCreatorsAtStartup;
207: }
208:
209: /**
210: * The log stream
211: */
212: private static final Log log = LogFactory
213: .getLog(DefaultCreatorManager.class);
214:
215: /**
216: * The list of the available creators
217: */
218: protected Map<String, Class<? extends Creator>> creatorTypes = new HashMap<String, Class<? extends Creator>>();
219:
220: /**
221: * The list of the configured creators
222: */
223: protected Map<String, Creator> creators = new HashMap<String, Creator>();
224:
225: /**
226: * Are we in debug mode?
227: */
228: protected boolean debug = false;
229:
230: /**
231: * Do we do full-create on startup?
232: */
233: protected boolean initApplicationScopeCreatorsAtStartup = false;
234:
235: /**
236: * The properties that we don't warn about if they don't exist.
237: * @see DefaultCreatorManager#addCreator(String, String, Map)
238: */
239: protected static List<String> ignore = Arrays.asList("creator",
240: "class");
241: }
|