1 /*************************************************************************
2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3  *
4  * Copyright 2000, 2010 Oracle and/or its affiliates.
5  *
6  * OpenOffice.org - a multi-platform office productivity suite
7  *
8  * This file is part of OpenOffice.org.
9  *
10  * OpenOffice.org is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU Lesser General Public License version 3
12  * only, as published by the Free Software Foundation.
13  *
14  * OpenOffice.org is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU Lesser General Public License version 3 for more details
18  * (a copy is included in the LICENSE file that accompanied this code).
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * version 3 along with OpenOffice.org.  If not, see
22  * <http://www.openoffice.org/license.html>
23  * for a copy of the LGPLv3 License.
24  *
25 ************************************************************************/
26 
27 #include "precompiled_ucb.hxx"
28 
29 #include "ucpext_provider.hxx"
30 #include "ucpext_content.hxx"
31 
32 /** === begin UNO includes === **/
33 /** === end UNO includes === **/
34 
35 #include <ucbhelper/contentidentifier.hxx>
36 #include <osl/diagnose.h>
37 #include <osl/mutex.hxx>
38 #include <comphelper/componentcontext.hxx>
39 #include <rtl/ustrbuf.hxx>
40 
41 //......................................................................................................................
42 namespace ucb { namespace ucp { namespace ext
43 {
44 //......................................................................................................................
45 
46 	/** === begin UNO using === **/
47 	using ::com::sun::star::uno::Reference;
48 	using ::com::sun::star::uno::XInterface;
49 	using ::com::sun::star::uno::UNO_QUERY;
50 	using ::com::sun::star::uno::UNO_QUERY_THROW;
51 	using ::com::sun::star::uno::UNO_SET_THROW;
52 	using ::com::sun::star::uno::Exception;
53 	using ::com::sun::star::uno::RuntimeException;
54 	using ::com::sun::star::uno::Any;
55 	using ::com::sun::star::uno::makeAny;
56 	using ::com::sun::star::uno::Sequence;
57 	using ::com::sun::star::uno::Type;
58     using ::com::sun::star::lang::XMultiServiceFactory;
59     using ::com::sun::star::ucb::XContentIdentifier;
60     using ::com::sun::star::ucb::IllegalIdentifierException;
61     using ::com::sun::star::ucb::XContent;
62     using ::com::sun::star::uno::XComponentContext;
63 	/** === end UNO using === **/
64 
65     //==================================================================================================================
66     //= ContentProvider
67     //==================================================================================================================
68     //------------------------------------------------------------------------------------------------------------------
69     ContentProvider::ContentProvider( const Reference< XMultiServiceFactory >& i_rServiceManager )
70         :ContentProvider_Base( i_rServiceManager )
71     {
72     }
73 
74     //------------------------------------------------------------------------------------------------------------------
75     ContentProvider::~ContentProvider()
76     {
77     }
78 
79     //------------------------------------------------------------------------------------------------------------------
80     ::rtl::OUString SAL_CALL ContentProvider::getImplementationName_static() throw (RuntimeException)
81     {
82         return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.comp.ucp.ext.ContentProvider" ) );
83     }
84 
85     //------------------------------------------------------------------------------------------------------------------
86     ::rtl::OUString SAL_CALL ContentProvider::getImplementationName() throw (RuntimeException)
87     {
88         return getImplementationName_static();
89     }
90 
91     //------------------------------------------------------------------------------------------------------------------
92     Sequence< ::rtl::OUString > SAL_CALL ContentProvider::getSupportedServiceNames_static(  ) throw (RuntimeException)
93     {
94         Sequence< ::rtl::OUString > aServiceNames(2);
95         aServiceNames[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ucb.ContentProvider" ) );
96         aServiceNames[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ucb.ExtensionContentProvider" ) );
97         return aServiceNames;
98     }
99 
100     //------------------------------------------------------------------------------------------------------------------
101     Sequence< ::rtl::OUString > SAL_CALL ContentProvider::getSupportedServiceNames(  ) throw (RuntimeException)
102     {
103         return getSupportedServiceNames_static();
104     }
105 
106     //------------------------------------------------------------------------------------------------------------------
107     Reference< XInterface > ContentProvider::Create( const Reference< XComponentContext >& i_rContext )
108     {
109         const ::comphelper::ComponentContext aContext( i_rContext );
110         return *( new ContentProvider( aContext.getLegacyServiceFactory() ) );
111     }
112 
113     //------------------------------------------------------------------------------------------------------------------
114     ::rtl::OUString ContentProvider::getRootURL()
115     {
116         return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.extension://" ) );
117     }
118 
119     //------------------------------------------------------------------------------------------------------------------
120     ::rtl::OUString ContentProvider::getArtificialNodeContentType()
121     {
122         return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "application/vnd.sun.star.extension-content" ) );
123     }
124 
125     //------------------------------------------------------------------------------------------------------------------
126     namespace
127     {
128         void lcl_ensureAndTransfer( ::rtl::OUString& io_rIdentifierFragment, ::rtl::OUStringBuffer& o_rNormalization, const sal_Unicode i_nLeadingChar )
129         {
130             if ( ( io_rIdentifierFragment.getLength() == 0 ) || ( io_rIdentifierFragment[0] != i_nLeadingChar ) )
131                 throw IllegalIdentifierException();
132             io_rIdentifierFragment = io_rIdentifierFragment.copy( 1 );
133             o_rNormalization.append( i_nLeadingChar );
134         }
135     }
136 
137     //------------------------------------------------------------------------------------------------------------------
138     Reference< XContent > SAL_CALL ContentProvider::queryContent( const Reference< XContentIdentifier  >& i_rIdentifier )
139         throw( IllegalIdentifierException, RuntimeException )
140     {
141         // Check URL scheme...
142         const ::rtl::OUString sScheme( rtl::OUString::createFromAscii( "vnd.sun.star.extension" ) );
143         if ( !i_rIdentifier->getContentProviderScheme().equalsIgnoreAsciiCase( sScheme ) )
144             throw IllegalIdentifierException();
145 
146         // normalize the identifier
147         const ::rtl::OUString sIdentifier( i_rIdentifier->getContentIdentifier() );
148 
149         // the scheme needs to be lower-case
150         ::rtl::OUStringBuffer aComposer;
151         aComposer.append( sIdentifier.copy( 0, sScheme.getLength() ).toAsciiLowerCase() );
152 
153         // one : is required after the scheme
154         ::rtl::OUString sRemaining( sIdentifier.copy( sScheme.getLength() ) );
155         lcl_ensureAndTransfer( sRemaining, aComposer, ':' );
156 
157         // and at least one /
158         lcl_ensureAndTransfer( sRemaining, aComposer, '/' );
159 
160         // the normalized form requires one additional /, but we also accept identifiers which don't have it
161         if ( sRemaining.getLength() == 0 )
162         {
163             // the root content is a special case, it requires ///
164             aComposer.appendAscii( "//" );
165         }
166         else
167         {
168             if ( sRemaining[0] != '/' )
169             {
170                 aComposer.append( sal_Unicode( '/' ) );
171                 aComposer.append( sRemaining );
172             }
173             else
174             {
175                 lcl_ensureAndTransfer( sRemaining, aComposer, '/' );
176                 // by now, we moved "vnd.sun.star.extension://" from the URL to aComposer
177                 if ( sRemaining.getLength() == 0 )
178                 {
179                     // again, it's the root content, but one / is missing
180                     aComposer.append( sal_Unicode( '/' ) );
181                 }
182                 else
183                 {
184                     aComposer.append( sRemaining );
185                 }
186             }
187         }
188         const Reference< XContentIdentifier > xNormalizedIdentifier( new ::ucbhelper::ContentIdentifier( m_xSMgr, aComposer.makeStringAndClear() ) );
189 
190         ::osl::MutexGuard aGuard( m_aMutex );
191 
192         // check if a content with given id already exists...
193         Reference< XContent > xContent( queryExistingContent( xNormalizedIdentifier ).get() );
194         if ( xContent.is() )
195             return xContent;
196 
197         // create a new content
198         xContent = new Content( m_xSMgr, this, xNormalizedIdentifier );
199         if ( !xContent->getIdentifier().is() )
200             throw IllegalIdentifierException();
201 
202         registerNewContent( xContent );
203         return xContent;
204     }
205 
206 //......................................................................................................................
207 } } }   // namespace ucb::ucp::ext
208 //......................................................................................................................
209