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.profiling.statistics;
018:
019: import java.io.IOException;
020: import java.util.Collection;
021: import java.util.Collections;
022: import java.util.Enumeration;
023: import java.util.HashMap;
024: import java.util.Map;
025:
026: import org.apache.avalon.framework.activity.Disposable;
027: import org.apache.avalon.framework.context.Context;
028: import org.apache.avalon.framework.context.ContextException;
029: import org.apache.avalon.framework.context.Contextualizable;
030: import org.apache.avalon.framework.logger.AbstractLogEnabled;
031: import org.apache.avalon.framework.service.ServiceException;
032: import org.apache.avalon.framework.service.ServiceManager;
033: import org.apache.avalon.framework.service.Serviceable;
034: import org.apache.avalon.framework.thread.ThreadSafe;
035: import org.apache.cocoon.auth.ApplicationUtil;
036: import org.apache.cocoon.auth.User;
037: import org.apache.cocoon.components.ContextHelper;
038: import org.apache.cocoon.environment.ObjectModelHelper;
039: import org.apache.cocoon.environment.Request;
040: import org.apache.cocoon.environment.Session;
041: import org.apache.excalibur.store.Store;
042: import org.apache.excalibur.store.StoreJanitor;
043:
044: /**
045: * Implementation for the statistics component.
046: * In order to prevent an out of memory exception we implement the Store
047: * interface (dummy implementation) so we can register this component with
048: * the StoreJanitor component which will invoke this component to free
049: * memory in case of low memory.
050: *
051: * @version $Id: CollectorImpl.java 485636 2006-12-11 12:20:15Z cziegeler $
052: * @since 2.1.10
053: */
054: public class CollectorImpl extends AbstractLogEnabled implements
055: Collector, Store, ThreadSafe, Serviceable, Disposable,
056: Contextualizable {
057:
058: private static final String COUNT_ATTRIBUTE = CollectorImpl.class
059: .getName();
060:
061: /** Are we currently collecting? */
062: protected boolean isCollecting = false;
063:
064: /** All reports. */
065: protected Map reports = new HashMap();
066:
067: /** All page reports. */
068: protected Map pageReports = new HashMap();
069:
070: /** The store janitor for registering ourself. */
071: protected StoreJanitor janitor;
072:
073: /** The service manager. */
074: protected ServiceManager manager;
075:
076: /** The component context. */
077: protected Context context;
078:
079: /**
080: * @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context)
081: */
082: public void contextualize(Context c) throws ContextException {
083: this .context = c;
084: }
085:
086: /**
087: * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
088: */
089: public void service(ServiceManager aManager)
090: throws ServiceException {
091: this .manager = aManager;
092: this .janitor = (StoreJanitor) this .manager
093: .lookup(StoreJanitor.ROLE);
094: this .janitor.register(this );
095: }
096:
097: /**
098: * @see org.apache.avalon.framework.activity.Disposable#dispose()
099: */
100: public void dispose() {
101: if (this .manager != null) {
102: if (this .janitor != null) {
103: this .janitor.unregister(this );
104: }
105: this .manager.release(this .janitor);
106: this .janitor = null;
107: this .manager = null;
108: }
109: }
110:
111: /**
112: * @see org.apache.cocoon.profiling.statistics.Collector#addStatistics(org.apache.cocoon.profiling.statistics.Statistics)
113: */
114: public void addStatistics(final Statistics stats) {
115: if (this .isCollecting && stats != null) {
116: // get report for this category
117: ReportImpl report = (ReportImpl) this .reports.get(stats
118: .getCategory());
119: if (report == null) {
120: synchronized (this ) {
121: report = (ReportImpl) this .reports.get(stats
122: .getCategory());
123: if (report == null) {
124: // create new report
125: report = new ReportImpl(stats.getCategory());
126: this .reports.put(stats.getCategory(), report);
127: }
128: }
129: }
130: synchronized (report) {
131: report.add(stats);
132: }
133: final String pageKey = this .getRequestKey();
134: PageReportImpl pageReport = (PageReportImpl) this .pageReports
135: .get(pageKey);
136: if (pageReport == null) {
137: pageReport = new PageReportImpl(pageKey);
138: this .pageReports.put(pageKey, pageReport);
139: }
140: pageReport.addStatistics(stats);
141: }
142: }
143:
144: /**
145: * @see org.apache.cocoon.profiling.statistics.Collector#getStatistics()
146: */
147: public Collection getStatistics() {
148: return this .reports.values();
149: }
150:
151: /**
152: * @see org.apache.cocoon.profiling.statistics.Collector#getPageReports()
153: */
154: public Collection getPageReports() {
155: return this .pageReports.values();
156: }
157:
158: /**
159: * @see org.apache.cocoon.profiling.statistics.Collector#isCollectingStatistics()
160: */
161: public boolean isCollectingStatistics() {
162: return this .isCollecting;
163: }
164:
165: /**
166: * @see org.apache.cocoon.profiling.statistics.Collector#setCollectingStatistics(boolean)
167: */
168: public void setCollectingStatistics(boolean value) {
169: this .isCollecting = value;
170: if (!this .isCollecting) {
171: this .reports.clear();
172: this .pageReports.clear();
173: }
174: }
175:
176: /**
177: * @see org.apache.cocoon.profiling.statistics.Collector#clear()
178: */
179: public void clear() {
180: this .reports.clear();
181: this .pageReports.clear();
182: }
183:
184: protected String getRequestKey() {
185: final Map objectModel = ContextHelper
186: .getObjectModel(this .context);
187: final User user = ApplicationUtil.getUser(objectModel);
188: final Request request = ObjectModelHelper
189: .getRequest(objectModel);
190: final Session session = request.getSession();
191: Integer counter = (Integer) request
192: .getAttribute(CollectorImpl.COUNT_ATTRIBUTE);
193: if (counter == null) {
194: counter = (Integer) session
195: .getAttribute(CollectorImpl.COUNT_ATTRIBUTE);
196: if (counter == null) {
197: counter = new Integer(0);
198: } else {
199: counter = new Integer(counter.intValue() + 1);
200: }
201: session
202: .setAttribute(CollectorImpl.COUNT_ATTRIBUTE,
203: counter);
204: request
205: .setAttribute(CollectorImpl.COUNT_ATTRIBUTE,
206: counter);
207: }
208: return (user == null ? "anon" : user.getId()) + ':'
209: + session.getId() + '/' + counter;
210: }
211:
212: /**
213: * @see org.apache.excalibur.store.Store#containsKey(java.lang.Object)
214: */
215: public boolean containsKey(Object arg0) {
216: return false;
217: }
218:
219: /**
220: * @see org.apache.excalibur.store.Store#free()
221: */
222: public void free() {
223: // we simply free everything
224: synchronized (this ) {
225: this .reports.clear();
226: this .pageReports.clear();
227: }
228: }
229:
230: /**
231: * @see org.apache.excalibur.store.Store#get(java.lang.Object)
232: */
233: public Object get(Object arg0) {
234: return null;
235: }
236:
237: /**
238: * @see org.apache.excalibur.store.Store#keys()
239: */
240: public Enumeration keys() {
241: return Collections.enumeration(Collections.EMPTY_LIST);
242: }
243:
244: /**
245: * @see org.apache.excalibur.store.Store#remove(java.lang.Object)
246: */
247: public void remove(Object arg0) {
248: // nothing to do here
249: }
250:
251: /**
252: * @see org.apache.excalibur.store.Store#size()
253: */
254: public int size() {
255: return this .reports.size();
256: }
257:
258: /**
259: * @see org.apache.excalibur.store.Store#store(java.lang.Object, java.lang.Object)
260: */
261: public void store(Object arg0, Object arg1) throws IOException {
262: // nothing to do here
263: }
264: }
|