Author: thomas.diesler(a)jboss.com
Date: 2006-12-21 13:01:41 -0500 (Thu, 21 Dec 2006)
New Revision: 1705
Added:
branches/tdiesler/trunk/integration-jboss42/src/resources/jbossws.beans/META-INF/
branches/tdiesler/trunk/integration-jboss42/src/resources/jbossws.beans/META-INF/jboss-beans.xml
branches/tdiesler/trunk/integration-jboss42/src/resources/jbossws.sar/
branches/tdiesler/trunk/integration-jboss42/src/resources/jbossws.sar/META-INF/
branches/tdiesler/trunk/integration-jboss42/src/resources/jbossws.sar/META-INF/jboss-service.xml
Removed:
branches/tdiesler/trunk/integration-jboss42/src/resources/jbossws.beans/jbossws-beans.xml
Modified:
branches/tdiesler/trunk/integration-jboss42/src/main/java/org/jboss/ws/integration/jboss42/DeployerInterceptor.java
branches/tdiesler/trunk/integration-jboss42/src/main/java/org/jboss/ws/integration/jboss42/DeployerInterceptorEJB.java
branches/tdiesler/trunk/integration-jboss42/src/main/java/org/jboss/ws/integration/jboss42/DeployerInterceptorJSE.java
branches/tdiesler/trunk/integration-jboss42/src/main/java/org/jboss/ws/integration/jboss42/DeploymentInfoAdaptor.java
branches/tdiesler/trunk/integration-jboss42/src/main/java/org/jboss/ws/integration/jboss42/ServiceEndpointPublisher.java
Log:
partial commit
Modified:
branches/tdiesler/trunk/integration-jboss42/src/main/java/org/jboss/ws/integration/jboss42/DeployerInterceptor.java
===================================================================
---
branches/tdiesler/trunk/integration-jboss42/src/main/java/org/jboss/ws/integration/jboss42/DeployerInterceptor.java 2006-12-21
15:27:43 UTC (rev 1704)
+++
branches/tdiesler/trunk/integration-jboss42/src/main/java/org/jboss/ws/integration/jboss42/DeployerInterceptor.java 2006-12-21
18:01:41 UTC (rev 1705)
@@ -23,6 +23,7 @@
//$Id$
+import org.jboss.deployment.DeploymentException;
import org.jboss.deployment.DeploymentInfo;
import org.jboss.deployment.MainDeployerMBean;
import org.jboss.deployment.SubDeployerInterceptorSupport;
@@ -67,17 +68,22 @@
/** Overwrite to create the webservice
*/
- protected Object create(Invocation invocation, DeploymentInfo di) throws Throwable
+ protected final Object create(Invocation invocation, DeploymentInfo di) throws
Throwable
{
log.debug("create: " + di.url);
-
Object retn = invokeNext(invocation);
if (isWebserviceDeployment(di))
{
- UnifiedDeploymentInfo udi = createUnifiedDeploymentInfo(di);
- di.context.put(UnifiedDeploymentInfo.class.getName(), udi);
- getServiceEndpointDeployer().create(udi);
+ try
+ {
+ createServiceEndpoint(di);
+ }
+ catch (Exception ex)
+ {
+ destroyServiceEndpoint(di);
+ DeploymentException.rethrowAsDeploymentException("Cannot create service
endpoint", ex);
+ }
}
return retn;
@@ -85,13 +91,56 @@
/** Overwrite to start the webservice
*/
- protected Object start(Invocation invocation, DeploymentInfo di) throws Throwable
+ protected final Object start(Invocation invocation, DeploymentInfo di) throws
Throwable
{
log.debug("start: " + di.url);
-
Object retn = invokeNext(invocation);
- UnifiedDeploymentInfo udi = getServiceEndpointDeployment(di);
+ try
+ {
+ startServiceEndpoint(di);
+ }
+ catch (Exception ex)
+ {
+ destroyServiceEndpoint(di);
+ DeploymentException.rethrowAsDeploymentException("Cannot start service
endpoint", ex);
+ }
+
+ return retn;
+ }
+
+ /** Overwrite to stop the webservice
+ */
+ protected final Object stop(Invocation invocation, DeploymentInfo di) throws
Throwable
+ {
+ log.debug("stop: " + di.url);
+
+ stopServiceEndpoint(di);
+
+ return invokeNext(invocation);
+ }
+
+ /** Overwrite to destroy the webservice
+ */
+ protected final Object destroy(Invocation invocation, DeploymentInfo di) throws
Throwable
+ {
+ log.debug("destroy: " + di.url);
+
+ destroyServiceEndpoint(di);
+
+ return invokeNext(invocation);
+ }
+
+ protected void createServiceEndpoint(DeploymentInfo di) throws Exception
+ {
+ UnifiedDeploymentInfo udi = createUnifiedDeploymentInfo(di);
+ di.context.put(UnifiedDeploymentInfo.class.getName(), udi);
+ getServiceEndpointDeployer().create(udi);
+ }
+
+ protected void startServiceEndpoint(DeploymentInfo di) throws Exception
+ {
+ UnifiedDeploymentInfo udi = getUnifiedDeploymentInfo(di);
if (udi != null)
{
// late initialization of the web context loader
@@ -103,38 +152,24 @@
getServiceEndpointDeployer().start(udi);
}
-
- return retn;
}
- /** Overwrite to stop the webservice
- */
- protected Object stop(Invocation invocation, DeploymentInfo di) throws Throwable
+ protected void stopServiceEndpoint(DeploymentInfo di) throws Exception
{
- log.debug("stop: " + di.url);
-
- UnifiedDeploymentInfo udi = getServiceEndpointDeployment(di);
+ UnifiedDeploymentInfo udi = getUnifiedDeploymentInfo(di);
if (udi != null)
{
getServiceEndpointDeployer().stop(udi);
}
-
- return invokeNext(invocation);
}
- /** Overwrite to destroy the webservice
- */
- protected Object destroy(Invocation invocation, DeploymentInfo di) throws Throwable
+ protected void destroyServiceEndpoint(DeploymentInfo di) throws Exception
{
- log.debug("destroy: " + di.url);
-
- UnifiedDeploymentInfo udi = getServiceEndpointDeployment(di);
+ UnifiedDeploymentInfo udi = getUnifiedDeploymentInfo(di);
if (udi != null)
{
getServiceEndpointDeployer().destroy(udi);
}
-
- return invokeNext(invocation);
}
protected ServiceEndpointDeployer getServiceEndpointDeployer()
@@ -150,14 +185,14 @@
KernelRegistryEntry entry =
registry.getEntry(AbstractServiceEndpointPublisher.BEAN_NAME);
return (AbstractServiceEndpointPublisher)entry.getTarget();
}
-
+
/** Return true if the deployment contains a web service endpoint
*/
protected abstract boolean isWebserviceDeployment(DeploymentInfo di);
- protected abstract UnifiedDeploymentInfo createUnifiedDeploymentInfo(DeploymentInfo
di) throws Throwable;
+ protected abstract UnifiedDeploymentInfo createUnifiedDeploymentInfo(DeploymentInfo
di) throws Exception;
- protected UnifiedDeploymentInfo getServiceEndpointDeployment(DeploymentInfo di)
+ protected UnifiedDeploymentInfo getUnifiedDeploymentInfo(DeploymentInfo di)
{
return
(UnifiedDeploymentInfo)di.context.get(UnifiedDeploymentInfo.class.getName());
}
Modified:
branches/tdiesler/trunk/integration-jboss42/src/main/java/org/jboss/ws/integration/jboss42/DeployerInterceptorEJB.java
===================================================================
---
branches/tdiesler/trunk/integration-jboss42/src/main/java/org/jboss/ws/integration/jboss42/DeployerInterceptorEJB.java 2006-12-21
15:27:43 UTC (rev 1704)
+++
branches/tdiesler/trunk/integration-jboss42/src/main/java/org/jboss/ws/integration/jboss42/DeployerInterceptorEJB.java 2006-12-21
18:01:41 UTC (rev 1705)
@@ -39,32 +39,28 @@
*/
public abstract class DeployerInterceptorEJB extends DeployerInterceptor
{
- protected Object create(Invocation invocation, DeploymentInfo di) throws Throwable
+ protected void createServiceEndpoint(DeploymentInfo di) throws Exception
{
- Object retObj = super.create(invocation, di);
+ super.createServiceEndpoint(di);
- UnifiedDeploymentInfo udi = getServiceEndpointDeployment(di);
+ UnifiedDeploymentInfo udi = getUnifiedDeploymentInfo(di);
if (udi != null)
{
UnifiedMetaData wsMetaData =
getServiceEndpointDeployer().getUnifiedMetaData(udi);
- udi.localUrl = generateWebDeployment(di, wsMetaData);
+ udi.expandedWebApp = generateWebDeployment(di, wsMetaData);
udi.context.put(DeploymentInfo.class.getName(), di);
getServiceEndpointPublisher().publishServiceEndpoint(udi);
}
-
- return retObj;
}
protected abstract URL generateWebDeployment(DeploymentInfo di, UnifiedMetaData
wsMetaData) throws IOException;
- protected Object destroy(Invocation invocation, DeploymentInfo di) throws Throwable
+ protected void destroyServiceEndpoint(DeploymentInfo di) throws Exception
{
- UnifiedDeploymentInfo udi = getServiceEndpointDeployment(di);
+ UnifiedDeploymentInfo udi = getUnifiedDeploymentInfo(di);
if (udi != null)
{
getServiceEndpointPublisher().destroyServiceEndpoint(udi);
}
-
- return super.destroy(invocation, di);
}
}
Modified:
branches/tdiesler/trunk/integration-jboss42/src/main/java/org/jboss/ws/integration/jboss42/DeployerInterceptorJSE.java
===================================================================
---
branches/tdiesler/trunk/integration-jboss42/src/main/java/org/jboss/ws/integration/jboss42/DeployerInterceptorJSE.java 2006-12-21
15:27:43 UTC (rev 1704)
+++
branches/tdiesler/trunk/integration-jboss42/src/main/java/org/jboss/ws/integration/jboss42/DeployerInterceptorJSE.java 2006-12-21
18:01:41 UTC (rev 1705)
@@ -59,7 +59,6 @@
URL webservicesURL = getWebservicesDescriptor(di);
udi = new JAXRPCDeployment(UnifiedDeploymentInfo.DeploymentType.JAXRPC_JSE,
webservicesURL);
DeploymentInfoAdaptor.buildDeploymentInfo(udi, di);
-
}
else if (type == UnifiedDeploymentInfo.DeploymentType.JAXWS_JSE)
{
@@ -78,17 +77,15 @@
*
* This implemantation modifies the servlet entries in web.xml
*/
- protected Object create(Invocation invocation, DeploymentInfo di) throws Throwable
+ protected void createServiceEndpoint(DeploymentInfo di) throws Exception
{
- Object retn = super.create(invocation, di);
-
- UnifiedDeploymentInfo udi = getServiceEndpointDeployment(di);
+ super.createServiceEndpoint(di);
+ UnifiedDeploymentInfo udi = getUnifiedDeploymentInfo(di);
if (udi != null)
{
AbstractServiceEndpointPublisher endpointPublisher =
getServiceEndpointPublisher();
endpointPublisher.rewriteWebXml(udi);
}
- return retn;
}
/** Return true if the deployment is a web service endpoint
Modified:
branches/tdiesler/trunk/integration-jboss42/src/main/java/org/jboss/ws/integration/jboss42/DeploymentInfoAdaptor.java
===================================================================
---
branches/tdiesler/trunk/integration-jboss42/src/main/java/org/jboss/ws/integration/jboss42/DeploymentInfoAdaptor.java 2006-12-21
15:27:43 UTC (rev 1704)
+++
branches/tdiesler/trunk/integration-jboss42/src/main/java/org/jboss/ws/integration/jboss42/DeploymentInfoAdaptor.java 2006-12-21
18:01:41 UTC (rev 1705)
@@ -23,6 +23,10 @@
// $Id$
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+
import org.jboss.deployment.DeploymentInfo;
import org.jboss.metadata.ApplicationMetaData;
import org.jboss.metadata.WebMetaData;
@@ -36,26 +40,38 @@
*/
public class DeploymentInfoAdaptor
{
- public static UnifiedDeploymentInfo buildDeploymentInfo(UnifiedDeploymentInfo udi,
DeploymentInfo di)
+ public static UnifiedDeploymentInfo buildDeploymentInfo(UnifiedDeploymentInfo udi,
DeploymentInfo di) throws Exception
{
if (di.parent != null)
{
udi.parent = new UnifiedDeploymentInfo(null);
buildDeploymentInfo(udi.parent, di.parent);
}
-
+
+ udi.name = di.getCanonicalName();
udi.simpleName = di.shortName;
- udi.url = di.url;
- udi.localUrl = di.localUrl;
+ udi.url = getDeploymentURL(di);
udi.metaData = buildMetaData(di.metaData);
- udi.annotationsCl = di.annotationsCl;
- udi.localCl = di.localCl;
- udi.ucl = di.ucl;
+ udi.classLoader = di.annotationsCl;
udi.deployedObject = di.deployedObject;
return udi;
}
+ private static URL getDeploymentURL(DeploymentInfo di) throws MalformedURLException
+ {
+ URL deploymentURL = (di.localUrl != null ? di.localUrl : di.url);
+ if ("file".equals(deploymentURL.getProtocol()))
+ {
+ String path = deploymentURL.getPath();
+ if (new File(path).isFile())
+ {
+ deploymentURL = new URL("jar:file:" + path + "!/");
+ }
+ }
+ return deploymentURL;
+ }
+
private static Object buildMetaData(Object metaData)
{
Object retMetaData = null;
Modified:
branches/tdiesler/trunk/integration-jboss42/src/main/java/org/jboss/ws/integration/jboss42/ServiceEndpointPublisher.java
===================================================================
---
branches/tdiesler/trunk/integration-jboss42/src/main/java/org/jboss/ws/integration/jboss42/ServiceEndpointPublisher.java 2006-12-21
15:27:43 UTC (rev 1704)
+++
branches/tdiesler/trunk/integration-jboss42/src/main/java/org/jboss/ws/integration/jboss42/ServiceEndpointPublisher.java 2006-12-21
18:01:41 UTC (rev 1705)
@@ -49,7 +49,7 @@
public String publishServiceEndpoint(UnifiedDeploymentInfo udi) throws Exception
{
- URL warURL = udi.localUrl;
+ URL warURL = udi.expandedWebApp;
DeploymentInfo di =
(DeploymentInfo)udi.context.get(DeploymentInfo.class.getName());
if (di == null)
throw new IllegalStateException("Cannot obtain DeploymentInfo from
context");
@@ -65,7 +65,7 @@
public String destroyServiceEndpoint(UnifiedDeploymentInfo udi) throws Exception
{
- getMainDeployer().undeploy(udi.localUrl);
+ getMainDeployer().undeploy(udi.expandedWebApp);
return "OK";
}
Added:
branches/tdiesler/trunk/integration-jboss42/src/resources/jbossws.beans/META-INF/jboss-beans.xml
===================================================================
---
branches/tdiesler/trunk/integration-jboss42/src/resources/jbossws.beans/META-INF/jboss-beans.xml 2006-12-21
15:27:43 UTC (rev 1704)
+++
branches/tdiesler/trunk/integration-jboss42/src/resources/jbossws.beans/META-INF/jboss-beans.xml 2006-12-21
18:01:41 UTC (rev 1705)
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<deployment
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="urn:jboss:bean-deployer bean-deployer_1_0.xsd"
+ xmlns="urn:jboss:bean-deployer">
+
+ <bean name="ServiceEndpointManager"
class="org.jboss.ws.core.server.ServiceEndpointManager">
+
+ <!--
+ The WSDL, that is a required deployment artifact for an endpoint, has a
<soap:address>
+ element which points to the location of the endpoint. JBoss supports rewriting of
that SOAP address.
+
+ If the content of <soap:address> is a valid URL, JBossWS will not rewrite
it unless 'alwaysModifySOAPAddress' is true.
+ If the content of <soap:address> is not a valid URL, JBossWS will rewrite
it using the attribute values given below.
+
+ If 'webServiceHost' is an empty string, JBossWS uses requesters host when
rewriting the <soap:address>.
+ -->
+ <property
name="webServiceHost">${jboss.bind.address}</property>
+ <property name="webServiceSecurePort">8443</property>
+ <property name="webServicePort">8080</property>
+ <property name="alwaysModifySOAPAddress">true</property>
+
+ <property
name="serviceEndpointInvokerJSE">org.jboss.ws.core.server.ServiceEndpointInvokerJSE</property>
+ <property
name="serviceEndpointInvokerEJB3">org.jboss.ws.integration.jboss42.ServiceEndpointInvokerEJB3</property>
+ <property
name="serviceEndpointInvokerEJB21">org.jboss.ws.integration.jboss42.ServiceEndpointInvokerEJB21</property>
+ <property
name="serviceEndpointInvokerMDB">org.jboss.ws.integration.jboss42.ServiceEndpointInvokerMDB</property>
+ </bean>
+
+ <bean name="ServiceEndpointDeployer"
class="org.jboss.ws.core.server.ServiceEndpointDeployer">
+ <property name="serviceEndpointManager">
+ <inject bean="ServiceEndpointManager"/>
+ </property>
+ </bean>
+
+ <bean name="ServiceEndpointPublisher"
class="org.jboss.ws.integration.jboss42.ServiceEndpointPublisher">
+ <property
name="serviceEndpointServlet">org.jboss.ws.integration.jboss42.JBossServiceEndpointServlet</property>
+ </bean>
+
+ <!-- A subscription manager for WS-Eventing -->
+ <bean name="SubscriptionManager"
class="org.jboss.ws.extensions.eventing.mgmt.SubscriptionManager"/>
+
+ <bean name="ServerConfig"
class="org.jboss.ws.integration.jboss42.ServerConfigImpl"/>
+
+ <bean name="KernelLocator"
class="org.jboss.ws.core.server.KernelLocator">
+ <!--property name="kernel"><inject
bean="jboss.kernel:service=Kernel"/></property-->
+ </bean>
+
+</deployment>
Property changes on:
branches/tdiesler/trunk/integration-jboss42/src/resources/jbossws.beans/META-INF/jboss-beans.xml
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
Deleted:
branches/tdiesler/trunk/integration-jboss42/src/resources/jbossws.beans/jbossws-beans.xml
===================================================================
---
branches/tdiesler/trunk/integration-jboss42/src/resources/jbossws.beans/jbossws-beans.xml 2006-12-21
15:27:43 UTC (rev 1704)
+++
branches/tdiesler/trunk/integration-jboss42/src/resources/jbossws.beans/jbossws-beans.xml 2006-12-21
18:01:41 UTC (rev 1705)
@@ -1,50 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<deployment xmlns="urn:jboss:bean-deployer:2.0">
-
- <bean name="ServiceEndpointManager"
class="org.jboss.ws.core.server.ServiceEndpointManager">
-
- <!--
- The WSDL, that is a required deployment artifact for an endpoint, has a
<soap:address>
- element which points to the location of the endpoint. JBoss supports rewriting of
that SOAP address.
-
- If the content of <soap:address> is a valid URL, JBossWS will not rewrite
it unless 'alwaysModifySOAPAddress' is true.
- If the content of <soap:address> is not a valid URL, JBossWS will rewrite
it using the attribute values given below.
-
- If 'webServiceHost' is an empty string, JBossWS uses requesters host when
rewriting the <soap:address>.
- -->
- <property
name="webServiceHost">${jboss.bind.address}</property>
- <property name="webServiceSecurePort">8443</property>
- <property name="webServicePort">8080</property>
- <property name="alwaysModifySOAPAddress">true</property>
-
- <property
name="serviceEndpointInvokerJSE">org.jboss.ws.core.server.ServiceEndpointInvokerJSE</property>
- <property
name="serviceEndpointInvokerEJB3">org.jboss.ws.integration.jboss42.ServiceEndpointInvokerEJB3</property>
- <property
name="serviceEndpointInvokerEJB21">org.jboss.ws.integration.jboss42.ServiceEndpointInvokerEJB21</property>
- <property
name="serviceEndpointInvokerMDB">org.jboss.ws.integration.jboss42.ServiceEndpointInvokerMDB</property>
- </bean>
-
- <bean name="ServiceEndpointDeployer"
class="org.jboss.ws.core.server.ServiceEndpointDeployer">
- <property name="serviceEndpointManager">
- <inject bean="ServiceEndpointManager"/>
- </property>
- </bean>
-
- <bean name="ServiceEndpointPublisher"
class="org.jboss.ws.integration.jboss42.JBoss42ServiceEndpointPublisher">
- <property name="mainDeployer"><inject
bean="MainDeployer"/></property>
- <property
name="serviceEndpointServlet">org.jboss.ws.integration.jboss42.JBossServiceEndpointServlet</property>
- </bean>
-
- <!-- Bind JAXRPC Service objects in application client environment context -->
- <bean name="ServiceRefHandler"
class="org.jboss.ws.integration.jboss42.ServiceRefHandler"/>
-
- <!-- A subscription manager for WS-Eventing -->
- <bean name="SubscriptionManager"
class="org.jboss.ws.extensions.eventing.mgmt.SubscriptionManager"/>
-
- <bean name="ServerConfig"
class="org.jboss.ws.integration.jboss42.ServerConfigImpl"/>
-
- <bean name="KernelLocator"
class="org.jboss.ws.core.server.KernelLocator">
- <!--property name="kernel"><inject
bean="jboss.kernel:service=Kernel"/></property-->
- </bean>
-
-</deployment>
Added:
branches/tdiesler/trunk/integration-jboss42/src/resources/jbossws.sar/META-INF/jboss-service.xml
===================================================================
---
branches/tdiesler/trunk/integration-jboss42/src/resources/jbossws.sar/META-INF/jboss-service.xml 2006-12-21
15:27:43 UTC (rev 1704)
+++
branches/tdiesler/trunk/integration-jboss42/src/resources/jbossws.sar/META-INF/jboss-service.xml 2006-12-21
18:01:41 UTC (rev 1705)
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- $Id$ -->
+
+<server>
+
+ <!--
+ A deployer service for WS clients.
+ -->
+ <mbean name="jboss.ws:service=WebServiceClientDeployer"
code="org.jboss.ws.integration.jboss42.WebServiceClientDeployer">
+ <depends>jboss:service=Naming</depends>
+ </mbean>
+
+ <!--
+ A deployer service for JSE endpoints.
+ -->
+ <mbean name="jboss.ws:service=WebServiceDeployerJSE"
code="org.jboss.ws.integration.jboss42.DeployerInterceptorJSE">
+ <depends-list optional-attribute-name="Interceptables">
+
<depends-list-element>jboss.web:service=WebServer</depends-list-element>
+ </depends-list>
+ </mbean>
+
+ <!--
+ A deployer service for EJB2.1 endpoints.
+ -->
+ <mbean name="jboss.ws:service=DeployerInterceptorEJB21"
code="org.jboss.ws.integration.jboss42.DeployerInterceptorEJB21">
+ <depends-list optional-attribute-name="Interceptables">
+
<depends-list-element>jboss.ejb:service=EJBDeployer</depends-list-element>
+ </depends-list>
+ </mbean>
+
+ <!--
+ A deployer service for EJB3 endpoints.
+ -->
+ <mbean name="jboss.ws:service=DeployerInterceptorEJB3"
code="org.jboss.ws.integration.jboss42.DeployerInterceptorEJB3">
+ <depends-list optional-attribute-name="Interceptables">
+
<depends-list-element>jboss.ejb3:service=EJB3Deployer</depends-list-element>
+ </depends-list>
+ </mbean>
+
+ <!--
+ A deployer service for JSE endpoints that are nested in service archives (sar).
+ -->
+ <mbean name="jboss.ws:service=DeployerInterceptorNestedJSE"
code="org.jboss.ws.integration.jboss42.DeployerInterceptorNestedJSE">
+ <depends optional-attribute-name="MainDeployer"
proxy-type="attribute">jboss.system:service=MainDeployer</depends>
+ <depends>jboss.ws:service=WebServiceDeployerJSE</depends>
+ </mbean>
+
+</server>
Property changes on:
branches/tdiesler/trunk/integration-jboss42/src/resources/jbossws.sar/META-INF/jboss-service.xml
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF