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.wicket.protocol.http.request.urlcompressing;
018:
019: import java.io.IOException;
020: import java.lang.ref.ReferenceQueue;
021: import java.lang.ref.WeakReference;
022: import java.util.Iterator;
023:
024: import org.apache.wicket.Component;
025: import org.apache.wicket.IClusterable;
026: import org.apache.wicket.util.collections.IntHashMap;
027: import org.apache.wicket.util.collections.IntHashMap.Entry;
028:
029: /**
030: * This class generates UID for Component/Interface combinations when used in
031: * conjunction with {@link UrlCompressingWebCodingStrategy}
032: *
033: * Use it like this:
034: *
035: * <pre>
036: * protected IRequestCycleProcessor newRequestCycleProcessor()
037: * {
038: * return new UrlCompressingWebRequestProcessor();
039: * }
040: * </pre>
041: *
042: * @since 1.2
043: *
044: * @see URLCompressingWebCodingStrategy
045: * @see UrlCompressingWebRequestProcessor
046: *
047: * @author jcompagner
048: */
049: public class UrlCompressor implements IClusterable {
050: /**
051: * @author jcompagner
052: */
053: public static class ComponentAndInterface {
054: private static final long serialVersionUID = 1L;
055:
056: private final IntKeyWeakReference ref;
057: private final String interfaceName;
058:
059: private ComponentAndInterface(IntKeyWeakReference ref,
060: String interfaceName) {
061: this .ref = ref;
062: this .interfaceName = interfaceName;
063: }
064:
065: /**
066: * @return Component The component that should be used to call the
067: * interface
068: */
069: public Component getComponent() {
070: return (Component) ref.get();
071: }
072:
073: /**
074: * @return String The interface name which should be called on the
075: * component
076: */
077: public String getInterfaceName() {
078: return interfaceName;
079: }
080: }
081:
082: private static class IntKeyWeakReference extends WeakReference {
083: private final int uid;
084:
085: /**
086: * @param uid
087: * @param referent
088: * @param q
089: */
090: public IntKeyWeakReference(int uid, Object referent,
091: ReferenceQueue q) {
092: super (referent, q);
093: this .uid = uid;
094: }
095: }
096:
097: private static final long serialVersionUID = 1L;
098:
099: private transient ReferenceQueue queue = new ReferenceQueue();
100:
101: private transient IntHashMap directComponentRefs = new IntHashMap(); // uid->component/interface
102:
103: private int uid = 1;
104:
105: /**
106: * Gets the combination
107: *
108: * @param uidString
109: * @return ComponentAndInterface
110: */
111: public ComponentAndInterface getComponentAndInterfaceForUID(
112: String uidString) {
113: IntKeyWeakReference ref = null;
114: while ((ref = (IntKeyWeakReference) queue.poll()) != null) {
115: directComponentRefs.remove(ref.uid);
116: }
117: int uid = Integer.parseInt(uidString);
118: ComponentAndInterface cai = (ComponentAndInterface) directComponentRefs
119: .get(uid);
120: return cai;
121: }
122:
123: /**
124: * @return the next uid for this url compressor
125: */
126: public int getNewUID() {
127: return uid++;
128: }
129:
130: /**
131: * Returns a uid for the combination component and the to call interface.
132: * Will return the same uid if it was already called for this specific
133: * combination.
134: *
135: * @param component
136: * The Component
137: * @param interfaceName
138: * The interface name
139: * @return int The uid for the component/interfaceName combination
140: */
141: public int getUIDForComponentAndInterface(Component component,
142: String interfaceName) {
143: int uid = 0;
144: Iterator it = directComponentRefs.entrySet().iterator();
145: while (it.hasNext()) {
146: IntHashMap.Entry entry = (IntHashMap.Entry) it.next();
147: ComponentAndInterface cai = (ComponentAndInterface) entry
148: .getValue();
149: if (cai.getInterfaceName().equals(interfaceName)
150: && cai.getComponent() == component) {
151: uid = entry.getKey();
152: break;
153: }
154: }
155: if (uid == 0) {
156: uid = getNewUID();
157: IntKeyWeakReference ref = new IntKeyWeakReference(uid,
158: component, queue);
159: directComponentRefs.put(uid, new ComponentAndInterface(ref,
160: interfaceName));
161: }
162: return uid;
163: }
164:
165: private void readObject(java.io.ObjectInputStream s)
166: throws IOException, ClassNotFoundException {
167: s.defaultReadObject();
168:
169: int size = s.readInt();
170: queue = new ReferenceQueue();
171: directComponentRefs = new IntHashMap((int) (size * 1.25));
172:
173: while (--size >= 0) {
174: int uid = s.readInt();
175: Component component = (Component) s.readObject();
176: String interfaceName = s.readUTF();
177:
178: IntKeyWeakReference ref = new IntKeyWeakReference(uid,
179: component, queue);
180: directComponentRefs.put(uid, new ComponentAndInterface(ref,
181: interfaceName));
182: }
183:
184: }
185:
186: private void writeObject(java.io.ObjectOutputStream s)
187: throws IOException {
188: IntKeyWeakReference ref = null;
189: while ((ref = (IntKeyWeakReference) queue.poll()) != null) {
190: directComponentRefs.remove(ref.uid);
191: }
192:
193: s.defaultWriteObject();
194:
195: s.writeInt(directComponentRefs.size());
196:
197: Iterator it = directComponentRefs.entrySet().iterator();
198: while (it.hasNext()) {
199: IntHashMap.Entry entry = (Entry) it.next();
200:
201: s.writeInt(entry.getKey());
202: ComponentAndInterface cai = (ComponentAndInterface) entry
203: .getValue();
204: s.writeObject(cai.getComponent());
205: s.writeUTF(cai.getInterfaceName());
206: }
207: }
208: }
|