You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@oltu.apache.org by to...@apache.org on 2010/12/18 18:08:45 UTC

svn commit: r1050675 - in /incubator/amber/trunk/oauth-2.0/oauth2-rs-filter: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/amber/ src/main/java/org/apache/amber/oauth2/ src/main/java/org/apache/a...

Author: tommaso
Date: Sat Dec 18 17:08:44 2010
New Revision: 1050675

URL: http://svn.apache.org/viewvc?rev=1050675&view=rev
Log:
[AMBER-12] - import of Leelo OAuth 2.0 implementation - rs-filter module

Added:
    incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/   (with props)
    incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/pom.xml   (with props)
    incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/src/
    incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/src/main/
    incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/src/main/java/
    incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/src/main/java/org/
    incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/src/main/java/org/apache/
    incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/src/main/java/org/apache/amber/
    incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/src/main/java/org/apache/amber/oauth2/
    incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/src/main/java/org/apache/amber/oauth2/rsfilter/
    incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/src/main/java/org/apache/amber/oauth2/rsfilter/OAuthClient.java   (with props)
    incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/src/main/java/org/apache/amber/oauth2/rsfilter/OAuthDecision.java   (with props)
    incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/src/main/java/org/apache/amber/oauth2/rsfilter/OAuthFilter.java   (with props)
    incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/src/main/java/org/apache/amber/oauth2/rsfilter/OAuthRSProvider.java   (with props)
    incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/src/main/java/org/apache/amber/oauth2/rsfilter/OAuthUtils.java   (with props)

Propchange: incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Sat Dec 18 17:08:44 2010
@@ -0,0 +1 @@
+target

Added: incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/pom.xml
URL: http://svn.apache.org/viewvc/incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/pom.xml?rev=1050675&view=auto
==============================================================================
--- incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/pom.xml (added)
+++ incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/pom.xml Sat Dec 18 17:08:44 2010
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+          Copyright 2010 Newcastle University
+
+             http://research.ncl.ac.uk/smart/
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You 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.
+
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <artifactId>amber-oauth2-parent</artifactId>
+        <groupId>org.apache.amber</groupId>
+        <version>0.2-SNAPSHOT</version>
+    </parent>
+    <artifactId>oauth2-rs-filter</artifactId>
+    <version>0.2-SNAPSHOT</version>
+    <name>Apache Amber: OAuth 2.0 Implementation - Resource Server Filter</name>
+
+    <build>
+        <finalName>oauth2-rs-filter</finalName>
+    </build>
+
+    <dependencies>
+        <dependency>
+            <artifactId>oauth2-resourceserver</artifactId>
+            <groupId>org.apache.amber</groupId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.amber</groupId>
+            <artifactId>oauth2-common</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+
+</project>

Propchange: incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/pom.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/src/main/java/org/apache/amber/oauth2/rsfilter/OAuthClient.java
URL: http://svn.apache.org/viewvc/incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/src/main/java/org/apache/amber/oauth2/rsfilter/OAuthClient.java?rev=1050675&view=auto
==============================================================================
--- incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/src/main/java/org/apache/amber/oauth2/rsfilter/OAuthClient.java (added)
+++ incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/src/main/java/org/apache/amber/oauth2/rsfilter/OAuthClient.java Sat Dec 18 17:08:44 2010
@@ -0,0 +1,32 @@
+/**
+ *       Copyright 2010 Newcastle University
+ *
+ *          http://research.ncl.ac.uk/smart/
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.amber.oauth2.rsfilter;
+
+/**
+ * @author Maciej Machulak (m.p.machulak@ncl.ac.uk)
+ * @author Lukasz Moren (lukasz.moren@ncl.ac.uk)
+ * @author Aad van Moorsel (aad.vanmoorsel@ncl.ac.uk)
+ */
+public interface OAuthClient {
+
+    String getClientId();
+}

Propchange: incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/src/main/java/org/apache/amber/oauth2/rsfilter/OAuthClient.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/src/main/java/org/apache/amber/oauth2/rsfilter/OAuthDecision.java
URL: http://svn.apache.org/viewvc/incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/src/main/java/org/apache/amber/oauth2/rsfilter/OAuthDecision.java?rev=1050675&view=auto
==============================================================================
--- incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/src/main/java/org/apache/amber/oauth2/rsfilter/OAuthDecision.java (added)
+++ incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/src/main/java/org/apache/amber/oauth2/rsfilter/OAuthDecision.java Sat Dec 18 17:08:44 2010
@@ -0,0 +1,39 @@
+/**
+ *       Copyright 2010 Newcastle University
+ *
+ *          http://research.ncl.ac.uk/smart/
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.amber.oauth2.rsfilter;
+
+import java.security.Principal;
+
+/**
+ * @author Maciej Machulak (m.p.machulak@ncl.ac.uk)
+ * @author Lukasz Moren (lukasz.moren@ncl.ac.uk)
+ * @author Aad van Moorsel (aad.vanmoorsel@ncl.ac.uk)
+ */
+public interface OAuthDecision {
+
+    boolean isAuthorized();
+
+    Principal getPrincipal();
+
+    OAuthClient getOAuthClient();
+
+}

Propchange: incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/src/main/java/org/apache/amber/oauth2/rsfilter/OAuthDecision.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/src/main/java/org/apache/amber/oauth2/rsfilter/OAuthFilter.java
URL: http://svn.apache.org/viewvc/incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/src/main/java/org/apache/amber/oauth2/rsfilter/OAuthFilter.java?rev=1050675&view=auto
==============================================================================
--- incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/src/main/java/org/apache/amber/oauth2/rsfilter/OAuthFilter.java (added)
+++ incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/src/main/java/org/apache/amber/oauth2/rsfilter/OAuthFilter.java Sat Dec 18 17:08:44 2010
@@ -0,0 +1,180 @@
+/**
+ *       Copyright 2010 Newcastle University
+ *
+ *          http://research.ncl.ac.uk/smart/
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.amber.oauth2.rsfilter;
+
+import java.io.IOException;
+import java.security.Principal;
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.amber.oauth2.common.OAuth;
+import org.apache.amber.oauth2.common.error.OAuthError;
+import org.apache.amber.oauth2.common.exception.OAuthProblemException;
+import org.apache.amber.oauth2.common.exception.OAuthSystemException;
+import org.apache.amber.oauth2.common.message.types.ParameterStyle;
+import org.apache.amber.oauth2.rs.request.OAuthAccessResourceRequest;
+import org.apache.amber.oauth2.rs.response.OAuthRSResponse;
+import org.apache.amber.oauth2.common.message.OAuthResponse;
+
+/**
+ * @author Maciej Machulak (m.p.machulak@ncl.ac.uk)
+ * @author Lukasz Moren (lukasz.moren@ncl.ac.uk)
+ * @author Aad van Moorsel (aad.vanmoorsel@ncl.ac.uk)
+ */
+public class OAuthFilter implements Filter {
+
+    public static final String OAUTH_RS_PROVIDER_CLASS = "oauth.rs.provider-class";
+
+    public static final String RS_REALM = "oauth.rs.realm";
+    public static final String RS_REALM_DEFAULT = "OAuth Protected Service";
+
+    public static final String RS_TOKENS = "oauth.rs.tokens";
+    public static final ParameterStyle RS_TOKENS_DEFAULT = ParameterStyle.HEADER;
+
+    private static final String TOKEN_DELIMITER = ",";
+
+    private String realm;
+
+    private OAuthRSProvider provider;
+
+    private ParameterStyle[] parameterStyles;
+
+
+    @Override
+    public void init(FilterConfig filterConfig) throws ServletException {
+
+        provider = OAuthUtils
+            .initiateServletContext(filterConfig.getServletContext(), OAUTH_RS_PROVIDER_CLASS,
+                OAuthRSProvider.class);
+        realm = filterConfig.getServletContext().getInitParameter(RS_REALM);
+        if (OAuthUtils.isEmpty(realm)) {
+            realm = RS_REALM_DEFAULT;
+        }
+
+        String parameterStylesString = filterConfig.getServletContext().getInitParameter(RS_TOKENS);
+        if (OAuthUtils.isEmpty(parameterStylesString)) {
+            parameterStyles = new ParameterStyle[] {RS_TOKENS_DEFAULT};
+        } else {
+            String[] parameters = parameterStylesString.split(TOKEN_DELIMITER);
+            if (parameters != null && parameters.length > 0) {
+                for (int i = 0; i < parameters.length; i++) {
+                    parameterStyles = new ParameterStyle[parameters.length];
+                    ParameterStyle tempParameterStyle = ParameterStyle.valueOf(parameters[i]);
+                    if (tempParameterStyle != null) {
+                        parameterStyles[i] = tempParameterStyle;
+                    } else {
+                        throw new ServletException("Incorrect ParameterStyle: " + parameters[i]);
+                    }
+                }
+            }
+        }
+
+    }
+
+    @Override
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+        throws IOException, ServletException {
+        HttpServletRequest req = (HttpServletRequest)request;
+        HttpServletResponse res = (HttpServletResponse)response;
+
+        try {
+
+            // Make an OAuth Request out of this servlet request
+            OAuthAccessResourceRequest oauthRequest = new OAuthAccessResourceRequest(req,
+                parameterStyles);
+
+            // Get the access token
+            String accessToken = oauthRequest.getAccessToken();
+
+            final OAuthDecision decision = provider.validateRequest(realm, accessToken, req);
+
+            request = new HttpServletRequestWrapper((HttpServletRequest)request) {
+                @Override
+                public Principal getUserPrincipal() {
+                    return decision.getPrincipal();
+                }
+
+            };
+
+            request.setAttribute(OAuth.OAUTH_CLIENT_ID, decision.getOAuthClient().getClientId());
+
+            chain.doFilter(request, response);
+            return;
+
+        } catch (OAuthSystemException e1) {
+            throw new ServletException(e1);
+        } catch (OAuthProblemException e) {
+            respondWithError(res, e);
+            return;
+        }
+
+    }
+
+
+    @Override
+    public void destroy() {
+
+    }
+
+    private void respondWithError(HttpServletResponse resp, OAuthProblemException error)
+        throws IOException, ServletException {
+
+        OAuthResponse oauthResponse = null;
+
+        try {
+            if (OAuthUtils.isEmpty(error.getError())) {
+                oauthResponse = OAuthRSResponse.errorResponse(HttpServletResponse.SC_UNAUTHORIZED)
+                    .setRealm(realm)
+                    .buildHeaderMessage();
+
+            } else {
+
+                int responseCode = 401;
+                if (error.getError().equals(OAuthError.CodeResponse.INVALID_REQUEST)) {
+                    responseCode = 400;
+                } else if (error.getError().equals(OAuthError.ResourceResponse.INSUFFICIENT_SCOPE)) {
+                    responseCode = 403;
+                }
+
+                oauthResponse = OAuthRSResponse
+                    .errorResponse(responseCode)
+                    .setRealm(realm)
+                    .setError(error.getError())
+                    .setErrorDescription(error.getDescription())
+                    .setErrorUri(error.getUri())
+                    .buildHeaderMessage();
+            }
+            resp.addHeader(OAuth.HeaderType.WWW_AUTHENTICATE,
+                oauthResponse.getHeader(OAuth.HeaderType.WWW_AUTHENTICATE));
+            resp.sendError(oauthResponse.getResponseStatus());
+        } catch (OAuthSystemException e) {
+            throw new ServletException(e);
+        }
+    }
+}

Propchange: incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/src/main/java/org/apache/amber/oauth2/rsfilter/OAuthFilter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/src/main/java/org/apache/amber/oauth2/rsfilter/OAuthRSProvider.java
URL: http://svn.apache.org/viewvc/incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/src/main/java/org/apache/amber/oauth2/rsfilter/OAuthRSProvider.java?rev=1050675&view=auto
==============================================================================
--- incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/src/main/java/org/apache/amber/oauth2/rsfilter/OAuthRSProvider.java (added)
+++ incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/src/main/java/org/apache/amber/oauth2/rsfilter/OAuthRSProvider.java Sat Dec 18 17:08:44 2010
@@ -0,0 +1,39 @@
+/**
+ *       Copyright 2010 Newcastle University
+ *
+ *          http://research.ncl.ac.uk/smart/
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.amber.oauth2.rsfilter;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.amber.oauth2.common.exception.OAuthProblemException;
+
+
+/**
+ * @author Maciej Machulak (m.p.machulak@ncl.ac.uk)
+ * @author Lukasz Moren (lukasz.moren@ncl.ac.uk)
+ * @author Aad van Moorsel (aad.vanmoorsel@ncl.ac.uk)
+ */
+public interface OAuthRSProvider {
+
+    OAuthDecision validateRequest(String rsId, String token, HttpServletRequest req) throws
+        OAuthProblemException;
+
+}
\ No newline at end of file

Propchange: incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/src/main/java/org/apache/amber/oauth2/rsfilter/OAuthRSProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/src/main/java/org/apache/amber/oauth2/rsfilter/OAuthUtils.java
URL: http://svn.apache.org/viewvc/incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/src/main/java/org/apache/amber/oauth2/rsfilter/OAuthUtils.java?rev=1050675&view=auto
==============================================================================
--- incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/src/main/java/org/apache/amber/oauth2/rsfilter/OAuthUtils.java (added)
+++ incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/src/main/java/org/apache/amber/oauth2/rsfilter/OAuthUtils.java Sat Dec 18 17:08:44 2010
@@ -0,0 +1,83 @@
+/**
+ *       Copyright 2010 Newcastle University
+ *
+ *          http://research.ncl.ac.uk/smart/
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.amber.oauth2.rsfilter;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+
+/**
+ * @author Maciej Machulak (m.p.machulak@ncl.ac.uk)
+ * @author Lukasz Moren (lukasz.moren@ncl.ac.uk)
+ * @author Aad van Moorsel (aad.vanmoorsel@ncl.ac.uk)
+ */
+public class OAuthUtils {
+
+    public static <T> T initiateServletContext(ServletContext context, String key, Class<T> expectedClass)
+        throws ServletException {
+
+        T provider = (T)context.getAttribute(key);
+
+        if (provider != null) {
+            return provider;
+        }
+
+        provider = (T)loadObject(context, key, expectedClass);
+
+        // set the provider and validator
+        context.setAttribute(key, provider);
+
+        return provider;
+    }
+
+    public static Object loadObject(ServletContext context, String classParamName, Class expectedClass)
+        throws ServletException {
+
+        Object ob = null;
+
+        String providerClassName = context.getInitParameter(classParamName);
+        if (isEmpty(providerClassName)) {
+            throw new ServletException(classParamName + " context param required");
+        }
+        try {
+            Class<?> clazz = Class.forName(providerClassName);
+            if (!expectedClass.isAssignableFrom(clazz)) {
+                throw new ServletException(classParamName + " class: " + providerClassName
+                    + " must be an instance of: " + expectedClass.getName());
+            }
+            ob = createObjectFromClassName(clazz);
+        } catch (ClassNotFoundException e) {
+            throw new ServletException(classParamName + " class " + providerClassName + " not found");
+        } catch (Exception e) {
+            throw new ServletException("Cannot instantiate: " + providerClassName);
+        }
+        return ob;
+    }
+
+    public static Object createObjectFromClassName(Class clazz)
+        throws IllegalAccessException, InstantiationException {
+        return clazz.newInstance();
+    }
+
+    public static boolean isEmpty(String value) {
+        return value == null || "".equals(value);
+    }
+}

Propchange: incubator/amber/trunk/oauth-2.0/oauth2-rs-filter/src/main/java/org/apache/amber/oauth2/rsfilter/OAuthUtils.java
------------------------------------------------------------------------------
    svn:eol-style = native