001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.components.accessor;
018:
019: import java.util.HashMap;
020: import java.util.Map;
021:
022: import org.apache.avalon.framework.CascadingRuntimeException;
023: import org.apache.avalon.framework.configuration.Configurable;
024: import org.apache.avalon.framework.configuration.Configuration;
025: import org.apache.avalon.framework.configuration.ConfigurationException;
026: import org.apache.avalon.framework.service.ServiceException;
027: import org.apache.avalon.framework.service.ServiceManager;
028: import org.apache.avalon.framework.service.ServiceSelector;
029: import org.apache.avalon.framework.service.Serviceable;
030: import org.apache.avalon.framework.thread.ThreadSafe;
031:
032: /**
033: * An accessor that handles a <code>Map</code> of accessors.
034: * @version $Id: MapAccessor.java 449189 2006-09-23 06:52:29Z crossley $
035: */
036: public class MapAccessor implements Accessor, Configurable,
037: Serviceable, ThreadSafe {
038:
039: /** Reference to the accessors */
040: private Map accessors;
041:
042: /** The service manager instance */
043: private ServiceManager manager;
044:
045: /**
046: * The accessors that should be part of the map are configured
047: * through <code><element name="the key that will be used in
048: * the map" accessor="the name of the accessor"/></code>.
049: *
050: * @see org.apache.avalon.framework.configuration.Configurable#configure(org.apache.avalon.framework.configuration.Configuration)
051: */
052: public void configure(Configuration config)
053: throws ConfigurationException {
054: Map accessors = new HashMap();
055: Configuration[] children = config.getChildren("element");
056: for (int i = 0; i < children.length; i++) {
057: String accessor = children[i].getAttribute("accessor");
058: // use the accessor name as name if nothing else is given
059: String name = children[i].getAttribute("name", accessor);
060: accessors.put(name, accessor);
061: }
062: this .accessors = new AccessorMap(accessors, this .manager);
063: }
064:
065: /**
066: * Set the current <code>ServiceManager</code> instance used by this
067: * <code>Serviceable</code>.
068: * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
069: */
070: public void service(ServiceManager manager) throws ServiceException {
071: this .manager = manager;
072: }
073:
074: /**
075: * Get the map of accessors
076: * @see org.apache.cocoon.components.accessor.Accessor#getObject()
077: */
078: public Object getObject() {
079: return this .accessors;
080: }
081:
082: /**
083: * Map that finds the accessor at access time.
084: */
085: public static class AccessorMap extends HashMap {
086:
087: private ServiceManager manager;
088:
089: public AccessorMap(Map map, ServiceManager manager) {
090: super (map);
091: this .manager = manager;
092: }
093:
094: public Object get(Object key) {
095: String accessorName = (String) super .get(key);
096: if (accessorName == null)
097: return null;
098: ServiceSelector accessorSelector = null;
099: Accessor accessor = null;
100: try {
101: // Thread safe accessors could be looked up once and be cached
102: accessorSelector = (ServiceSelector) this .manager
103: .lookup(Accessor.ROLE + "Selector");
104: accessor = (Accessor) accessorSelector
105: .select(accessorName);
106: return accessor.getObject();
107: } catch (ServiceException e) {
108: // FIXME: Don't know if this is the appropriate action
109: throw new CascadingRuntimeException(
110: "Trying to access non existing acessor: "
111: + accessorName, e);
112: } finally {
113: accessorSelector.release(accessor);
114: this .manager.release(accessorSelector);
115: }
116: }
117:
118: // The MapAccessor is thread safe so the map should be read only
119: public void clear() {
120: throw new UnsupportedOperationException(
121: "AccessorMap is read only");
122: }
123:
124: public Object put(Object key, Object value) {
125: throw new UnsupportedOperationException(
126: "AccessorMap is read only");
127: }
128:
129: public void putAll(Map m) {
130: throw new UnsupportedOperationException(
131: "AccessorMap is read only");
132: }
133:
134: public Object remove(Object key) {
135: throw new UnsupportedOperationException(
136: "AccessorMap is read only");
137: }
138: }
139: }
|