View Javadoc

1   /**
2    * Pyx4me framework
3    * Copyright (C) 2006-2008 pyx4j.com.
4    * 
5    * Licensed under the Apache License, Version 2.0 (the "License");
6    * you may not use this file except in compliance with the License.
7    * You may obtain a copy of the License at
8    *
9    * http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing,
12   * software distributed under the License is distributed on an
13   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14   * KIND, either express or implied.  See the License for the
15   * specific language governing permissions and limitations
16   * under the License.
17   * 
18   * @author vlads
19   * @version $Id: ServiceSearchMojo.java 2066 2008-06-21 23:16:18Z vlads $
20   */
21  package com.pyx4me.maven.obex;
22  
23  import java.io.IOException;
24  import java.util.StringTokenizer;
25  
26  import javax.bluetooth.BluetoothStateException;
27  import javax.bluetooth.DeviceClass;
28  import javax.bluetooth.DiscoveryListener;
29  import javax.bluetooth.LocalDevice;
30  import javax.bluetooth.RemoteDevice;
31  import javax.bluetooth.ServiceRecord;
32  import javax.bluetooth.UUID;
33  
34  import org.apache.maven.plugin.MojoExecutionException;
35  import org.apache.maven.plugin.MojoFailureException;
36  import org.apache.maven.plugin.logging.Log;
37  import org.apache.maven.project.MavenProject;
38  
39  /**
40   * The obex:search task finds OBEX Object Push Service on device.
41   * 
42   * @author vlads
43   * 
44   * @goal search
45   * @description Finds OBEX Object Push Service on device.
46   */
47  public class ServiceSearchMojo extends AbstractDeviceMojo {
48  
49  	/**
50  	 * The Maven project reference where the plugin is currently being executed.
51  	 * The default value is populated from maven.
52  	 * 
53  	 * @parameter expression="${project}"
54  	 * @readonly
55  	 * @required
56  	 */
57  	protected MavenProject mavenProject;
58  
59  	public void execute() throws MojoExecutionException, MojoFailureException {
60  		if (serverSufix == null) {
61  			findOBEX(getServerConfig(null), getLog());
62  		} else {
63  			if (serverSufix.startsWith(",")) {
64  				findOBEX(getServerConfig(null), getLog());
65  			}
66  			StringTokenizer tok = new StringTokenizer(serverSufix, ",");
67  			while (tok.hasMoreTokens()) {
68  				findOBEX(getServerConfig(tok.nextToken()), getLog());
69  			}
70  		}
71  	}
72  
73  	private static class RemoteDeviceExt extends RemoteDevice {
74  		public RemoteDeviceExt(String address) {
75  			super(address);
76  		}
77  	}
78  
79  	private static class BluetoothServiceSearch implements DiscoveryListener {
80  
81  		public final UUID L2CAP = new UUID(0x0100);
82  
83  		public final UUID RFCOMM = new UUID(0x0003);
84  
85  		public final UUID OBEX = new UUID(0x0008);
86  
87  		public final UUID OBEX_OBJECT_PUSH = new UUID(0x1105);
88  
89  		public final UUID OBEX_FILE_TRANSFER = new UUID(0x1106);
90  
91  		Log log;
92  
93  		boolean inquiring;
94  
95  		int servicesSearchTransID;
96  
97  		String serviceURL;
98  
99  		BluetoothServiceSearch(Log log) {
100 			this.log = log;
101 		}
102 
103 		public boolean startServiceSearch(RemoteDevice device) {
104 			inquiring = false;
105 			serviceURL = null;
106 			try {
107 				UUID[] searchUuidSet = new UUID[] { L2CAP, RFCOMM, OBEX_OBJECT_PUSH };
108 				int[] attrIDs = new int[] { 0x0100 // Service name
109 				};
110 
111 				servicesSearchTransID = LocalDevice.getLocalDevice().getDiscoveryAgent().searchServices(attrIDs,
112 						searchUuidSet, device, this);
113 			} catch (BluetoothStateException e) {
114 				log.error("Cannot start inquiry", e);
115 				return false;
116 			}
117 			inquiring = true;
118 			return inquiring;
119 		}
120 
121 		public void deviceDiscovered(RemoteDevice btDevice, DeviceClass cod) {
122 		}
123 
124 		public void inquiryCompleted(int discType) {
125 		}
126 
127 		public void servicesDiscovered(int transID, ServiceRecord[] servRecord) {
128 			for (int i = 0; i < servRecord.length; i++) {
129 				String url = servRecord[i].getConnectionURL(ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false);
130 				if (url == null) {
131 					continue;
132 				}
133 				int schemeEnd = url.indexOf("://");
134 				if (schemeEnd == -1) {
135 					continue;
136 				}
137 				String scheme = url.substring(0, schemeEnd);
138 				if (!scheme.equals("btgoep")) {
139 					continue;
140 				}
141 				int hostEnd = url.indexOf(':', scheme.length() + 3);
142 				if (hostEnd == -1) {
143 					continue;
144 				}
145 				String host = url.substring(scheme.length() + 3, hostEnd);
146 				String paramsStr = url.substring(hostEnd + 1);
147 				StringTokenizer tok = new StringTokenizer(paramsStr, ";");
148 				String port;
149 				if (tok.hasMoreTokens()) {
150 					port = tok.nextToken();
151 				} else {
152 					port = paramsStr;
153 				}
154 
155 				serviceURL = host + ":" + port;
156 
157 				log.info("  -> found service: " + serviceURL);
158 			}
159 		}
160 
161 		public void serviceSearchCompleted(int transID, int respCode) {
162 			switch (respCode) {
163 			case SERVICE_SEARCH_ERROR:
164 				log.info("  -> Error occurred while processing the service search");
165 				break;
166 			case SERVICE_SEARCH_TERMINATED:
167 				break;
168 			case SERVICE_SEARCH_DEVICE_NOT_REACHABLE:
169 				log.info("  -> Device not reachable");
170 				break;
171 			default:
172 				if (serviceURL == null) {
173 					log.info("  -> OBEX Object Push service not found");
174 				}
175 			}
176 			inquiring = false;
177 		}
178 
179 	}
180 
181 	private static String getFriendlyName(RemoteDevice device) {
182 		try {
183 			String name = device.getFriendlyName(false);
184 			if ((name == null) || (name.length() == 0)) {
185 				return device.getBluetoothAddress();
186 			} else {
187 				return name;
188 			}
189 		} catch (IOException e) {
190 			return device.getBluetoothAddress();
191 		}
192 	}
193 
194 	private String findOBEX(ServerConfig cfg, Log log) {
195 		configureBlueCove(cfg, log);
196 		String addr = cfg.url;
197 		int hostEnd = addr.indexOf(':');
198 		if (hostEnd != -1) {
199 			addr = addr.substring(0, hostEnd);
200 		}
201 		return findOBEX(addr, cfg.alias, log);
202 	}
203 
204 	public static String findOBEX(String btAddress, String alias, Log log) {
205 		RemoteDevice device = new RemoteDeviceExt(btAddress);
206 		if (alias == null) {
207 			alias = getFriendlyName(device);
208 		}
209 		log.info("OBEX Service Search on " + alias);
210 
211 		BluetoothServiceSearch bss = new BluetoothServiceSearch(log);
212 		if (!bss.startServiceSearch(device)) {
213 			log.error("Cannot start inquiry");
214 		} else {
215 			while (bss.inquiring) {
216 				try {
217 					Thread.sleep(1000);
218 				} catch (Exception e) {
219 				}
220 			}
221 		}
222 		return bss.serviceURL;
223 	}
224 
225 }