001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019 package org.apache.geronimo.specs.activation;
020
021 import java.io.BufferedReader;
022 import java.io.InputStream;
023 import java.io.InputStreamReader;
024 import java.net.URL;
025 import java.util.Map;
026 import java.util.concurrent.ConcurrentMap;
027 import java.util.concurrent.ConcurrentHashMap;
028
029 import javax.activation.MailcapCommandMap;
030 import javax.activation.CommandMap;
031
032 import org.osgi.framework.Bundle;
033 import org.osgi.framework.BundleEvent;
034 import org.osgi.service.log.LogService;
035 import org.osgi.util.tracker.BundleTrackerCustomizer;
036
037 public class CommandMapBundleTrackerCustomizer implements BundleTrackerCustomizer {
038 // our base Activator (used as a service source)
039 private Activator activator;
040 // the bundle hosting the activation code
041 private Bundle activationBundle;
042 // the accumulated list of provider bundles that have command definitions
043 private ConcurrentMap<Long, URL> mailCaps = new ConcurrentHashMap<Long, URL>();
044
045 public CommandMapBundleTrackerCustomizer(Activator a, Bundle b) {
046 activator = a;
047 activationBundle = b;
048 }
049
050 /**
051 * Handle the activation of a new bundle.
052 *
053 * @param bundle The source bundle.
054 * @param event The bundle event information.
055 *
056 * @return A return object.
057 */
058 @Override
059 public Object addingBundle(Bundle bundle, BundleEvent event) {
060 if (bundle.equals(activationBundle)) {
061 return null;
062 }
063
064 return registerBundle(bundle);
065 }
066
067 /**
068 * Perform the check for an existing mailcap file when
069 * a bundle is registered.
070 *
071 * @param bundle The potential provider bundle.
072 *
073 * @return A URL object if this bundle contains a mailcap file.
074 */
075 private Object registerBundle(Bundle bundle) {
076 URL url = bundle.getResource("/META-INF/mailcap");
077 if (url != null) {
078 log(LogService.LOG_DEBUG, "found mailcap at " + url);
079 mailCaps.put(bundle.getBundleId(), url);
080 rebuildCommandMap();
081 }
082 // the url marks our interest in additional activity for this
083 // bundle.
084 return url;
085 }
086
087
088 /**
089 * Remove a bundle from our potential mailcap pool.
090 *
091 * @param bundle The potential source bundle.
092 */
093 protected void unregisterBundle(Bundle bundle) {
094 URL mailcap = mailCaps.remove(bundle.getBundleId());
095 if (mailcap != null ){
096 log(LogService.LOG_DEBUG, "removing mailcap at " + mailcap);
097 rebuildCommandMap();
098 }
099 }
100
101
102 @Override
103 public void modifiedBundle(Bundle bundle, BundleEvent event, Object object) {
104 log(LogService.LOG_DEBUG, "Bundle Considered for mailcap providers: " + bundle.getSymbolicName());
105 // this will update for the new bundle
106 registerBundle(bundle);
107 }
108
109 @Override
110 public void removedBundle(Bundle bundle, BundleEvent event, Object object) {
111 unregisterBundle(bundle);
112 }
113
114 private void log(int level, String message) {
115 activator.log(level, message);
116 }
117
118 private void log(int level, String message, Throwable th) {
119 activator.log(level, message, th);
120 }
121
122 /**
123 * Rebuild a new default command map after a change in
124 * the status of bundles providing command maps.
125 */
126 private void rebuildCommandMap() {
127 MailcapCommandMap commandMap = new MailcapCommandMap();
128 for (URL url : mailCaps.values()) {
129 try {
130 InputStream is = url.openStream();
131 try {
132 BufferedReader br = new BufferedReader(new InputStreamReader(is));
133 String line;
134 while ((line = br.readLine()) != null) {
135 commandMap.addMailcap(line);
136 }
137 } finally {
138 is.close();
139 }
140 } catch (Exception e) {
141 // Ignore
142 }
143 }
144 // this is our new default command map
145 CommandMap.setDefaultCommandMap(commandMap);
146 }
147 }