Added: incubator/wave/trunk/src/org/waveprotocol/box/waveimport/google/oauth/OAuthedFetchService.java URL: http://svn.apache.org/viewvc/incubator/wave/trunk/src/org/waveprotocol/box/waveimport/google/oauth/OAuthedFetchService.java?rev=1244643&view=auto ============================================================================== --- incubator/wave/trunk/src/org/waveprotocol/box/waveimport/google/oauth/OAuthedFetchService.java (added) +++ incubator/wave/trunk/src/org/waveprotocol/box/waveimport/google/oauth/OAuthedFetchService.java Wed Feb 15 19:03:40 2012 @@ -0,0 +1,167 @@ +/* + * Copyright 2011 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.waveprotocol.box.waveimport.google.oauth; + +import com.google.common.base.Charsets; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; +import com.google.inject.Inject; + +import java.io.IOException; +import java.util.List; +import java.util.logging.Logger; +import org.apache.commons.httpclient.Header; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.URIException; +import org.apache.commons.httpclient.methods.EntityEnclosingMethod; + +/** + * A fetch service that signs fetch requests with OAuth2. + * + * @author [email protected] (David Hearnden) + * @author [email protected] (Christian Ohler) + */ +public final class OAuthedFetchService { + + /** + * Detects whether an HTTP response indicates that the OAuth token has + * expired. + */ + public interface TokenRefreshNeededDetector { + boolean refreshNeeded(int responseCode, Header[] responseHeaders, byte[] responseContent) throws IOException; + } + + public static final TokenRefreshNeededDetector RESPONSE_CODE_401_DETECTOR = + new TokenRefreshNeededDetector() { + @Override public boolean refreshNeeded(int responseCode, Header[] responseHeaders, byte[] responseContent) { + return responseCode == 401; + } + }; + + @SuppressWarnings("unused") + private static final Logger log = Logger.getLogger(OAuthedFetchService.class.getName()); + + private final HttpClient fetch; + private final OAuthRequestHelper helper; + + @Inject + public OAuthedFetchService(HttpClient fetch, OAuthRequestHelper helper) { + this.fetch = fetch; + this.helper = helper; + } + + private String describeRequest(EntityEnclosingMethod req) throws URIException { + StringBuilder b = new StringBuilder(req.getName() + " " + req.getURI()); + for (Header h : req.getRequestHeaders()) { + b.append("\n" + h.getName() + ": " + h.getValue()); + } + return "" + b; + } + + private String describeResponse(int responseCode, Header[] responseHeaders, byte[] responseBody, boolean includeBody) { + StringBuilder b = new StringBuilder(responseCode + + " with " + responseBody.length + " bytes of content"); + for (Header h : responseHeaders) { + b.append("\n" + h.getName() + ": " + h.getValue()); + } + if (includeBody) { + b.append("\n" + new String(responseBody, Charsets.UTF_8)); + } else { + b.append("\n<content elided>"); + } + return "" + b; + } + + private int fetch1(EntityEnclosingMethod req, TokenRefreshNeededDetector refreshNeeded, + boolean tokenJustRefreshed) throws IOException { + log.info("Sending request (token just refreshed: " + tokenJustRefreshed + "): " + + describeRequest(req)); + helper.authorize(req); + //log.info("req after authorizing: " + describeRequest(req)); + int code = fetch.executeMethod(req); + log.info("response: " + describeResponse(code, req.getResponseHeaders(), req.getResponseBody(), false)); + if (refreshNeeded.refreshNeeded(code, req.getResponseHeaders(), req.getResponseBody())) { + if (tokenJustRefreshed) { + throw new NeedNewOAuthTokenException("Token just refreshed, still no good: " + + describeResponse(code, req.getResponseHeaders(), req.getResponseBody(), true)); + } else { + helper.refreshToken(); + return fetch1(req, refreshNeeded, true); + } + } else { + return code; + } + } + + public int fetch(EntityEnclosingMethod request, TokenRefreshNeededDetector refreshNeeded) + throws IOException { + return fetch1(request, refreshNeeded, false); + } + + public int fetch(EntityEnclosingMethod request) throws IOException { + return fetch(request, RESPONSE_CODE_401_DETECTOR); + } + + // TODO(ohler): Move these static utility methods to some other utility class. + + /** Gets the values of all headers with the name {@code headerName}. */ + public static List<String> getHeaders(Header[] respHeaders, String headerName) { + ImmutableList.Builder<String> b = ImmutableList.builder(); + for (Header h : respHeaders) { + // HTTP header names are case-insensitive. App Engine downcases them when + // deployed but not when running locally. + if (headerName.equalsIgnoreCase(h.getName())) { + b.add(h.getValue()); + } + } + return b.build(); + } + + /** + * Checks that exactly one header named {@code headerName} is present and + * returns its value. + */ + public static String getSingleHeader(Header[] respHeaders, String headerName) { + return Iterables.getOnlyElement(getHeaders(respHeaders, headerName)); + } + + /** Returns the body of {@code resp}, assuming that its encoding is UTF-8. */ + private static String getUtf8ResponseBodyUnchecked(byte[] respContent) { + if (respContent == null) { + return ""; + } else { + return new String(respContent, Charsets.UTF_8); + } + } + + /** + * Checks that the Content-Type of {@code resp} is + * {@code expectedUtf8ContentType} (which is assumed to imply UTF-8 encoding) + * and returns the body as a String. + */ + public static String getUtf8ResponseBody(Header[] respHeaders, byte[] respContent, String expectedUtf8ContentType) + throws IOException { + String contentType = getSingleHeader(respHeaders, "Content-Type"); + if (!expectedUtf8ContentType.equals(contentType)) { + throw new IOException("Unexpected Content-Type: " + contentType + + " (wanted " + expectedUtf8ContentType + "); body as UTF-8: " + + getUtf8ResponseBodyUnchecked(respContent)); + } + return getUtf8ResponseBodyUnchecked(respContent); + } + +}
Added: incubator/wave/trunk/src/org/waveprotocol/box/waveimport/google/oauth/StableUserId.java URL: http://svn.apache.org/viewvc/incubator/wave/trunk/src/org/waveprotocol/box/waveimport/google/oauth/StableUserId.java?rev=1244643&view=auto ============================================================================== --- incubator/wave/trunk/src/org/waveprotocol/box/waveimport/google/oauth/StableUserId.java (added) +++ incubator/wave/trunk/src/org/waveprotocol/box/waveimport/google/oauth/StableUserId.java Wed Feb 15 19:03:40 2012 @@ -0,0 +1,59 @@ +/* + * Copyright 2011 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.waveprotocol.box.waveimport.google.oauth; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.base.Objects; + +import java.io.Serializable; + +/** + * A stable user identifier: a string that uniquely identifies a user and + * remains the same even if e.g. the e-mail address changes, and will not be + * re-used even if an account is deleted. + * + * @author [email protected] (Christian Ohler) + */ +public class StableUserId implements Serializable { + + private final String id; + + public StableUserId(String id) { + this.id = checkNotNull(id, "Null id"); + } + + public String getId() { + return id; + } + + @Override public String toString() { + return "StableUserId(" + id + ")"; + } + + @Override public final boolean equals(Object o) { + if (o == this) { return true; } + if (!(o instanceof StableUserId)) { return false; } + StableUserId other = (StableUserId) o; + return Objects.equal(id, other.id); + } + + @Override public final int hashCode() { + return Objects.hashCode(id); + } + +} Added: incubator/wave/trunk/src/org/waveprotocol/box/waveimport/google/oauth/UserContext.java URL: http://svn.apache.org/viewvc/incubator/wave/trunk/src/org/waveprotocol/box/waveimport/google/oauth/UserContext.java?rev=1244643&view=auto ============================================================================== --- incubator/wave/trunk/src/org/waveprotocol/box/waveimport/google/oauth/UserContext.java (added) +++ incubator/wave/trunk/src/org/waveprotocol/box/waveimport/google/oauth/UserContext.java Wed Feb 15 19:03:40 2012 @@ -0,0 +1,127 @@ +/* + * Copyright 2011 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.waveprotocol.box.waveimport.google.oauth; + +import com.google.common.base.Preconditions; +import com.google.inject.servlet.RequestScoped; + +import org.waveprotocol.wave.model.wave.ParticipantId; + +import java.util.logging.Logger; + +import javax.annotation.Nullable; + +/** + * Holds information about the user we are acting as. Many helper classes + * receive a {@code UserContext} for making OAuth requests or for attributing + * actions (for example, incoming deltas) to the current user. + * + * For each request, this starts out unintialized, since we have no uniform way + * of identifying the user. Authentication filters like + * {@link InteractiveAuthFilter} and {@link RpcAuthFilter} implement different + * means of identifying the user and populate the {@code UserContext} + * accordingly, including reading OAuth credentials from persistent storage. + * + * Servlets like {@link OAuthCallbackHandler} that need to manipulate + * credentials in special ways populate the {@link UserContext} directly. + * + * Attempting to call a getter method while the corresponding information is not + * present will result in an exception. This makes it easy to tell when + * a servlet is not using the right authentication filter. + * + * This class is not thread-safe; if we ever use more than one thread for a + * single request, we'll have to think about thread safety. + * + * This class is structurally similar to {@link AccountStore.Record} but plays a + * very different role -- {@code UserContext} is mutable to allow authentication + * filters (and other classes that handle login) to pass information about the + * current user to other classes that need it, while {@code AccountStore.Record} + * is an immutable in-memory representation of a record in {@link AccountStore}. + * + * @author [email protected] (Christian Ohler) + */ +@RequestScoped +public class UserContext { + + @SuppressWarnings("unused") + private static final Logger log = Logger.getLogger(UserContext.class.getName()); + + // At some point, we might want to refactor this to allow the auth filters to + // perform retrieval of the OAuth credentials lazily -- many servlets don't + // need credentials (or need them only in some cases), and the redundant + // datastore read is undesirable. However, once we cache credentials in + // memcache, we will merely be doing a redundant memcache lookup, which is + // less of a problem. So implementing this laziness is not urgent. + + @Nullable private StableUserId userId = null; + @Nullable private ParticipantId participantId = null; + @Nullable private OAuthCredentials oAuthCredentials = null; + + public UserContext() { + } + + public boolean hasUserId() { + return userId != null; + } + + public StableUserId getUserId() { + Preconditions.checkState(hasUserId(), "No userId: %s", this); + return userId; + } + + public UserContext setUserId(@Nullable StableUserId userId) { + this.userId = userId; + return this; + } + + public boolean hasParticipantId() { + return participantId != null; + } + + public ParticipantId getParticipantId() { + Preconditions.checkState(hasParticipantId(), "No participantId: %s", this); + return participantId; + } + + public UserContext setParticipantId(@Nullable ParticipantId participantId) { + this.participantId = participantId; + return this; + } + + public boolean hasOAuthCredentials() { + return oAuthCredentials != null; + } + + public OAuthCredentials getOAuthCredentials() { + Preconditions.checkState(hasOAuthCredentials(), "No oAuthCredentials: %s", this); + return oAuthCredentials; + } + + public UserContext setOAuthCredentials(@Nullable OAuthCredentials oAuthCredentials) { + this.oAuthCredentials = oAuthCredentials; + return this; + } + + @Override public String toString() { + return "UserContext(" + + userId + ", " + + participantId + ", " + + oAuthCredentials + + ")"; + } + +} Added: incubator/wave/trunk/test/org/waveprotocol/box/server/waveserver/ImportServletTest.java URL: http://svn.apache.org/viewvc/incubator/wave/trunk/test/org/waveprotocol/box/server/waveserver/ImportServletTest.java?rev=1244643&view=auto ============================================================================== --- incubator/wave/trunk/test/org/waveprotocol/box/server/waveserver/ImportServletTest.java (added) +++ incubator/wave/trunk/test/org/waveprotocol/box/server/waveserver/ImportServletTest.java Wed Feb 15 19:03:40 2012 @@ -0,0 +1,104 @@ +/** + * Copyright 2012 A. Kaplanov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.waveprotocol.box.server.waveserver; + +import java.util.HashSet; +import java.util.Set; + +import junit.framework.TestCase; + +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import static org.mockito.Mockito.when; + +import org.waveprotocol.box.server.common.CoreWaveletOperationSerializer; +import org.waveprotocol.wave.federation.Proto.ProtocolWaveletDelta; +import org.waveprotocol.wave.federation.Proto.ProtocolWaveletOperation; +import org.waveprotocol.wave.model.version.HashedVersion; + +import org.waveprotocol.box.server.util.testing.TestingConstants; +import org.waveprotocol.wave.model.wave.InvalidParticipantAddress; +import org.waveprotocol.wave.model.wave.ParticipantId; + +/** + * @author [email protected] (Andrew Kaplanov) + */ +public class ImportServletTest extends TestCase implements TestingConstants { + + private static final HashedVersion VERSION = HashedVersion.unsigned(111L); + + private static final String FROM_DOMAIN = "googlewave.com"; + private static final String FROM_USER = USER_NAME + "@" + FROM_DOMAIN; + + private static final ProtocolWaveletDelta DELTA_ADD_USER = ProtocolWaveletDelta.newBuilder() + .setAuthor(FROM_USER) + .setHashedVersion(CoreWaveletOperationSerializer.serialize(VERSION)) + .addOperation(ProtocolWaveletOperation.newBuilder().setAddParticipant(FROM_USER)).build(); + + private static final ProtocolWaveletDelta DELTA_REMOVE_USER = ProtocolWaveletDelta.newBuilder() + .setAuthor(FROM_USER) + .setHashedVersion(CoreWaveletOperationSerializer.serialize(VERSION)) + .addOperation(ProtocolWaveletOperation.newBuilder().setRemoveParticipant(FROM_USER)).build(); + + private static final ProtocolWaveletDelta DELTA_FROM_PUBLIC_USER = ProtocolWaveletDelta.newBuilder() + .setAuthor(ImportServlet.GWAVE_PUBLIC_USER_NAME + "@" + ImportServlet.GWAVE_PUBLIC_DOMAIN) + .setHashedVersion(CoreWaveletOperationSerializer.serialize(VERSION)) + .addOperation(ProtocolWaveletOperation.newBuilder().setNoOp(true)).build(); + + @Mock + LocalWaveletContainerImpl wavelet; + + @Override + protected void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + when(wavelet.getCurrentVersion()).thenReturn(VERSION); + } + + public void testSubstitutionOfUserName() throws WaveletStateException, InvalidParticipantAddress { + ProtocolWaveletDelta delta = ImportServlet.convertDelta(DELTA_ADD_USER, DOMAIN, wavelet, + WAVELET_NAME, new HashSet<ParticipantId>()); + assertEquals(USER, delta.getAuthor()); + assertEquals(USER, delta.getOperation(0).getAddParticipant()); + } + + public void testSkippingAdditionOfDuplicateUser() throws WaveletStateException, InvalidParticipantAddress { + Set<ParticipantId> participants = new HashSet<ParticipantId>(); + ProtocolWaveletDelta delta; + + delta = ImportServlet.convertDelta(DELTA_ADD_USER, DOMAIN, wavelet, + WAVELET_NAME, participants); + + delta = ImportServlet.convertDelta(DELTA_ADD_USER, DOMAIN, wavelet, + WAVELET_NAME, participants); + + assertTrue(delta.getOperation(0).hasNoOp()); + } + + public void testSkippingRemovalOfNonExistentUser() throws InvalidParticipantAddress { + ProtocolWaveletDelta delta = ImportServlet.convertDelta(DELTA_REMOVE_USER, DOMAIN, wavelet, + WAVELET_NAME, new HashSet<ParticipantId>()); + assertTrue(delta.getOperation(0).hasNoOp()); + } + + public void testSubstitutionOfPublicUserName() throws WaveletStateException, InvalidParticipantAddress { + ProtocolWaveletDelta delta = ImportServlet.convertDelta(DELTA_FROM_PUBLIC_USER, DOMAIN, wavelet, + WAVELET_NAME, new HashSet<ParticipantId>()); + assertEquals(ImportServlet.WIAB_SHARED_USER_NAME + "@" + DOMAIN, delta.getAuthor()); + } + +} Added: incubator/wave/trunk/third_party/runtime/google-api-client/COPYING URL: http://svn.apache.org/viewvc/incubator/wave/trunk/third_party/runtime/google-api-client/COPYING?rev=1244643&view=auto ============================================================================== --- incubator/wave/trunk/third_party/runtime/google-api-client/COPYING (added) +++ incubator/wave/trunk/third_party/runtime/google-api-client/COPYING Wed Feb 15 19:03:40 2012 @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. Added: incubator/wave/trunk/third_party/runtime/google-api-client/README URL: http://svn.apache.org/viewvc/incubator/wave/trunk/third_party/runtime/google-api-client/README?rev=1244643&view=auto ============================================================================== --- incubator/wave/trunk/third_party/runtime/google-api-client/README (added) +++ incubator/wave/trunk/third_party/runtime/google-api-client/README Wed Feb 15 19:03:40 2012 @@ -0,0 +1,11 @@ +URL: http://code.google.com/p/google-api-java-client/wiki/OAuth2Draft10 +Version: 1.5 +License: Apache 2.0 + +License File: COPYING + +Description: +Google APIs Client Libraries + +Local Modifications: +Class-Path field was removed from /META-INF/MANIFEST.MF files. Added: incubator/wave/trunk/third_party/runtime/google-api-client/google-api-client-1.5.0-beta.jar URL: http://svn.apache.org/viewvc/incubator/wave/trunk/third_party/runtime/google-api-client/google-api-client-1.5.0-beta.jar?rev=1244643&view=auto ============================================================================== Files incubator/wave/trunk/third_party/runtime/google-api-client/google-api-client-1.5.0-beta.jar (added) and incubator/wave/trunk/third_party/runtime/google-api-client/google-api-client-1.5.0-beta.jar Wed Feb 15 19:03:40 2012 differ Added: incubator/wave/trunk/third_party/runtime/google-api-client/google-http-client-1.5.0-beta.jar URL: http://svn.apache.org/viewvc/incubator/wave/trunk/third_party/runtime/google-api-client/google-http-client-1.5.0-beta.jar?rev=1244643&view=auto ============================================================================== Files incubator/wave/trunk/third_party/runtime/google-api-client/google-http-client-1.5.0-beta.jar (added) and incubator/wave/trunk/third_party/runtime/google-api-client/google-http-client-1.5.0-beta.jar Wed Feb 15 19:03:40 2012 differ Added: incubator/wave/trunk/third_party/runtime/google-api-client/google-oauth-client-1.5.0-beta.jar URL: http://svn.apache.org/viewvc/incubator/wave/trunk/third_party/runtime/google-api-client/google-oauth-client-1.5.0-beta.jar?rev=1244643&view=auto ============================================================================== Files incubator/wave/trunk/third_party/runtime/google-api-client/google-oauth-client-1.5.0-beta.jar (added) and incubator/wave/trunk/third_party/runtime/google-api-client/google-oauth-client-1.5.0-beta.jar Wed Feb 15 19:03:40 2012 differ
