001: /*
002: * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package com.sun.tools.internal.xjc.reader;
027:
028: import java.lang.reflect.Constructor;
029: import java.lang.reflect.InvocationTargetException;
030: import java.util.HashMap;
031: import java.util.Map;
032:
033: import com.sun.tools.internal.xjc.ErrorReceiver;
034: import com.sun.tools.internal.xjc.model.Model;
035:
036: /**
037: * Holds all the binding related singleton components in a "ring",
038: * and let you access those components, creating them as necessary.
039: *
040: * <p>
041: * A {@link Ring} is local to a thread,
042: * and only one instanceof {@link Ring} can be active at any given time.
043: *
044: * Use {@link #begin()} and {@link #end(Ring)} to start/end a ring scope.
045: * Inside a scope, use {@link #get()} to obtain the instance.
046: *
047: * <p>
048: * When a {@link Model} is built by the reader, an active {@link Ring} scope
049: * is assumed.
050: *
051: *
052: * <h2>Components in Ring</h2>
053: * <p>
054: * Depending on the schema language we are dealing with, different
055: * components are in the model. But at least the following components
056: * are in the ring.
057: *
058: * <ul>
059: * <li>{@link ErrorReceiver}
060: * </ul>
061: *
062: * @author Kohsuke Kawaguchi
063: */
064: public final class Ring {
065:
066: private final Map<Class, Object> components = new HashMap<Class, Object>();
067:
068: private static final ThreadLocal<Ring> instances = new ThreadLocal<Ring>() {
069: public Ring initialValue() {
070: return new Ring();
071: }
072: };
073:
074: private Ring() {
075: }
076:
077: public static <T> void add(Class<T> clazz, T instance) {
078: assert !get().components.containsKey(clazz);
079: get().components.put(clazz, instance);
080: }
081:
082: public static <T> void add(T o) {
083: add((Class<T>) o.getClass(), o);
084: }
085:
086: public static <T> T get(Class<T> key) {
087: T t = (T) get().components.get(key);
088: if (t == null) {
089: try {
090: Constructor<T> c = key.getDeclaredConstructor();
091: c.setAccessible(true);
092: t = c.newInstance();
093: if (!get().components.containsKey(key))
094: // many components register themselves.
095: add(key, t);
096: } catch (InstantiationException e) {
097: throw new Error(e);
098: } catch (IllegalAccessException e) {
099: throw new Error(e);
100: } catch (NoSuchMethodException e) {
101: throw new Error(e);
102: } catch (InvocationTargetException e) {
103: throw new Error(e);
104: }
105: }
106:
107: assert t != null;
108: return t;
109: }
110:
111: /**
112: * A {@link Ring} instance is associated with a thread.
113: */
114: public static Ring get() {
115: return instances.get();
116: }
117:
118: /**
119: * Starts a new scope.
120: */
121: public static Ring begin() {
122: Ring r = instances.get();
123: instances.set(new Ring());
124: return r;
125: }
126:
127: /**
128: * Ends a scope.
129: */
130: public static void end(Ring old) {
131: instances.set(old);
132: }
133: }
|