View Javadoc

1   /*
2    * Copyright (C) 2012 Atlassian
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package com.atlassian.jira.rest.client.internal.async;
17  
18  import com.atlassian.event.api.EventPublisher;
19  import com.atlassian.httpclient.apache.httpcomponents.DefaultHttpClient;
20  import com.atlassian.httpclient.api.HttpClient;
21  import com.atlassian.httpclient.api.Request;
22  import com.atlassian.httpclient.api.factory.HttpClientOptions;
23  import com.atlassian.httpclient.spi.ThreadLocalContextManagers;
24  import com.atlassian.jira.rest.client.api.AuthenticationHandler;
25  import com.atlassian.sal.api.ApplicationProperties;
26  import com.atlassian.util.concurrent.Effect;
27  import org.slf4j.Logger;
28  import org.slf4j.LoggerFactory;
29  
30  import java.io.File;
31  import java.io.IOException;
32  import java.io.InputStream;
33  import java.net.URI;
34  import java.util.Date;
35  import java.util.Properties;
36  
37  /**
38   * Factory for asynchronous http clients.
39   *
40   * @since v2.0
41   */
42  public class AsynchronousHttpClientFactory {
43  
44  	@SuppressWarnings("unchecked")
45  	public DisposableHttpClient createClient(final URI serverUri, final AuthenticationHandler authenticationHandler) {
46  		final HttpClientOptions options = new HttpClientOptions();
47  		options.setRequestPreparer(new Effect<Request>() {
48  			@Override
49  			public void apply(final Request request) {
50  				authenticationHandler.configure(request);
51  			}
52  		});
53  		final DefaultHttpClient defaultHttpClient = new DefaultHttpClient(new NoOpEventPublisher(),
54  				new RestClientApplicationProperties(serverUri),
55  				ThreadLocalContextManagers.noop(), options);
56  		return new AtlassianHttpClientDecorator(defaultHttpClient) {
57  
58  			@Override
59  			public void destroy() throws Exception {
60  				defaultHttpClient.destroy();
61  			}
62  		};
63  	}
64  
65  	public DisposableHttpClient createClient(final HttpClient client) {
66  		return new AtlassianHttpClientDecorator(client) {
67  
68  			@Override
69  			public void destroy() throws Exception {
70  				// This should never be implemented. This is simply creation of a wrapper
71  				// for AtlassianHttpClient which is extended by a destroy method.
72  				// Destroy method should never be called for AtlassianHttpClient coming from
73  				// a client! Imagine you create a RestClient, pass your own HttpClient there
74  				// and it gets destroy.
75  			}
76  		};
77  	}
78  
79  	private static class NoOpEventPublisher implements EventPublisher {
80  		@Override
81  		public void publish(Object o) {
82  		}
83  
84  		@Override
85  		public void register(Object o) {
86  		}
87  
88  		@Override
89  		public void unregister(Object o) {
90  		}
91  
92  		@Override
93  		public void unregisterAll() {
94  		}
95  	}
96  
97  	/**
98  	 * These properties are used to present JRJC as a User-Agent during http requests.
99  	 */
100 	@SuppressWarnings("deprecation")
101 	private static class RestClientApplicationProperties implements ApplicationProperties {
102 
103 		private final String baseUrl;
104 
105 		private RestClientApplicationProperties(URI jiraURI) {
106 			this.baseUrl = jiraURI.getPath();
107 		}
108 
109 		@Override
110 		public String getBaseUrl() {
111 			return baseUrl;
112 		}
113 
114 		@Override
115 		public String getDisplayName() {
116 			return "Atlassian JIRA Rest Java Client";
117 		}
118 
119 		@Override
120 		public String getVersion() {
121 			return MavenUtils.getVersion("com.atlassian.jira", "jira-rest-java-com.atlassian.jira.rest.client");
122 		}
123 
124 		@Override
125 		public Date getBuildDate() {
126 			// TODO implement using MavenUtils, JRJC-123
127 			throw new UnsupportedOperationException();
128 		}
129 
130 		@Override
131 		public String getBuildNumber() {
132 			// TODO implement using MavenUtils, JRJC-123
133 			return String.valueOf(0);
134 		}
135 
136 		@Override
137 		public File getHomeDirectory() {
138 			return new File(".");
139 		}
140 
141 		@Override
142 		public String getPropertyValue(final String s) {
143 			throw new UnsupportedOperationException("Not implemented");
144 		}
145 	}
146 
147 	private static final class MavenUtils {
148 		private static final Logger logger = LoggerFactory.getLogger(MavenUtils.class);
149 
150 		private static final String UNKNOWN_VERSION = "unknown";
151 
152 		static String getVersion(String groupId, String artifactId) {
153 			final Properties props = new Properties();
154 			InputStream resourceAsStream = null;
155 			try {
156 				resourceAsStream = MavenUtils.class.getResourceAsStream(String
157 						.format("/META-INF/maven/%s/%s/pom.properties", groupId, artifactId));
158 				props.load(resourceAsStream);
159 				return props.getProperty("version", UNKNOWN_VERSION);
160 			} catch (Exception e) {
161 				logger.debug("Could not find version for maven artifact {}:{}", groupId, artifactId);
162 				logger.debug("Got the following exception", e);
163 				return UNKNOWN_VERSION;
164 			} finally {
165 				if (resourceAsStream != null) {
166 					try {
167 						resourceAsStream.close();
168 					} catch (IOException ioe) {
169 						// ignore
170 					}
171 				}
172 			}
173 		}
174 	}
175 
176 }